Mybatis优化,添加日志,给实体类起别名,联表查询,xml特殊字符
- Mybatis优化
- 添加日志
- 解决属性名和字段名不一致的情况
- 为实体类起别名(不建议使用)
- 实体的属性和数据库表的字段不一致
- 联表查询
- 多对一
- 创建对应的实体类
- 映射文件
- 一对多
- xml碰到特殊字符如何处理
Mybatis优化
可以把数据源的信息抽取到db.properties文件中。
db.properties文件
jdbc.driverName:jdbc驱动
jdbc.url:数据库的路径
jdbc.userName:数据库用户的账户
jdbc.passWord:数据库用户的密码
///代表localhost:3306
以下两种写法是一个意思
jdbc.url=jdbc:mysql:///mybatis?characterEncoding=utf8&useUnicode=true&useOldAliasMetadataBehavior=true&useSSL=false
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&useUnicode=true&useOldAliasMetadataBehavior=true&useSSL=false
db.properties文件
jdbc.driverName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis?characterEncoding=utf8&useUnicode=true&useOldAliasMetadataBehavior=true&useSSL=false
jdbc.userName=root
jdbc.passWord=root
再db.properties文件中引入mybatis-config.xml文件中
<properties resource="db.properties"/>
注意:这里的value要用${},中间写引入db.properties文件的属性,如下:
<property name="driver" value="${jdbc.driverName}"/>
<!-- ppp代表连接数据库的表-->
<property name="url" value="${jdbc.url}"/>
<!-- username代表数据库的用户名-->
<property name="username" value="${jdbc.userName}"/>
<!-- password代表数据库的密码-->
<property name="password" value="${jdbc.passWord}"/>
整体mybatis-config.xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引入properties文件-->
<properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<!-- JDBC:代表使用的事务管理类型,默认打开事务,操作之后需要手动提交-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverName}"/>
<!-- ppp代表连接数据库的表-->
<property name="url" value="${jdbc.url}"/>
<!-- username代表数据库的用户名-->
<property name="username" value="${jdbc.userName}"/>
<!-- password代表数据库的密码-->
<property name="password" value="${jdbc.passWord}"/>
</dataSource>
</environment>
</environments>
<!-- 将mapper映射放入mybatis.xml中-->
<mappers>
<mapper resource="mapper/ClassMapper.xml"/>
</mappers>
</configuration>
添加日志
(1)在pom.xml中引入log4j文件
<!-- 引入log4j文件 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
(2)创建日志的配置文件 log4j.properties
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
控制台输出如下:
2021-03-22 10:03:25,494 [main] DEBUG [com.zz.dao.ClassDao.findClassById] - ==> Preparing: SELECT * from class c, teacher t ,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=1
2021-03-22 10:03:25,514 [main] DEBUG [com.zz.dao.ClassDao.findClassById] - ==> Parameters:
2021-03-22 10:03:25,534 [main] DEBUG [com.zz.dao.ClassDao.findClassById] - <== Total: 3
Clazz(cid=1, cname=bj_a, teacher=Teacher(tid=1, tName=LS1), students=[Student(sid=1, sName=xs_A, classId=1), Student(sid=2, sName=xs_B, classId=1), Student(sid=3, sName=xs_C, classId=1)])
解决属性名和字段名不一致的情况
为实体类起别名(不建议使用)
1.在mybatis-config.xml
(1)给单个类起别名
<!--给单个类起别名-->
<typeAliases>
<typeAlias type="com.zz.entity.User" alias="User"/>
</typeAliases>
(2)给指定包下的所有类起别名,类名就是别名
resultType中填的就是mybatis-config.xml中 alias="User"的User
<!--给指定包下的类起别名,就是类的名称-->
<typeAliases>
<package name="com.zz.entity" />
</typeAliases>
2.在mapper.xml映射文件中
resultType中填的就是该类
<!-- 给单个类起别名-->
<select id="selectAll" resultType="User">
select * password from user
</select>
resultType中填的就是该类
<!--给指定包下的类起别名,就是类的名称-->
<select id="selectAll" resultType="User">
select * from user
</select>
实体的属性和数据库表的字段不一致
(1)为查询的结果起别名-----与属性名一致。
<!--给字段起别名-->
<select id="findClassById" resultType="Clazz">
select c_id cid,c_name cname,teacher_id teacherId from class c ,teacher t where c.teacher_id=t.t_id and c_id=#{cid}
</select>
(2)使用resultMap来创建属性与字段的映射关系
id:代表主键
result:代表其他字段
column:代表数据库字段
property:映射数据库列的字段或属性(代表实体类字段)
resultMap 里面的id代表它的标识,type代表使用哪种类作为其映射的类,可以是别名或者全限定名
resultMap 里面的type代表使用哪种类作为其映射的类,可以是别名或者全限定名。(java实体类的类型)
resultMap 与resultType两者只能用一个
<!-- type表示java实体类的类型-->
<resultMap id="BaseMap" type="com.zz.entity.User">
<!-- id表示主键
column:表示字段
property:实体类的属性
-->
<id column="u_id" property="id"/>
<!-- result表示其他字段-->
<result column="u_username" property="username"/>
<result column="u_password" property="password"/>
</resultMap>
<!-- 给查询的结果起别名-->
<select id="selectAll" resultMap="BaseMap">
select * from users
</select>
联表查询
多对一
(1)表与表之间的关系------->外键【逻辑外键】
数据库表teacher
CREATE TABLE teacher(
t_id INT PRIMARY KEY AUTO_INCREMENT,
t_name VARCHAR(20)
);
//teacher class 一对多
CREATE TABLE class(
c_id INT PRIMARY KEY AUTO_INCREMENT,
c_name VARCHAR(20),
teacher_id INT -- 外键
);
ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id)
REFERENCES teacher(t_id);
INSERT INTO teacher(t_name) VALUES('LS1');
INSERT INTO teacher(t_name) VALUES('LS2');
INSERT INTO class(c_name, teacher_id) VALUES('bj_a', 1);
INSERT INTO class(c_name, teacher_id) VALUES('bj_b', 2);
(2)java实体类如何维持这种关系。
Teacher {tid, tname}
Class {cid,cname,Teacher teacher}
-->class 只包含老师id号。 多对一 可以在多的实体中添加一的实体类对象。
(3)要求根据班级号 查询班级信息并带上老师的信息。
创建对应的实体类
(1)Clazz实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Clazz {
private int cid;
private String cname;
// 该班级对应的老师信息
private Teacher teacher;
// 表示该班级下所有的学生信息
private List<Student> student;
}
Teacher实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int tid;
private String tname;
}
映射文件
(1)第一种方法:联表查询只要引用的是对象就用resultMap
引入的是对象就用association
association :表示一对一关系
association 里面的property代表映射数据库列的字段或属性(代表实体类字段)
association 里面的javaType代表返回类型,跟resultType一个意思
mapper.xml中
<resultMap id="ClazzMap" type="com.zz.entity.Clazz">
<!-- id代表主键-->
<id column="c_id" property="cid"/>
<!-- result代表其他属性-->
<result column="c_name" property="cname"/>
<!-- association代表多对一映射-->
<!-- 如果引入的是对象-->
<association property="teacher" javaType="com.zz.entity.Teacher">
<!-- 该属性的名字与字段的对应关系-->
<id column="t_id" property="tid"/>
<result column="t_name" property="tname"/>
</association>
</resultMap>
<!-- 只要使用联表查询,必须使用resultMap-->
<select id="findClassById" resultMap="ClazzMap">
select * from class c ,teacher t where c.teacher_id=t.t_id and c.c_id=#{cid};
</select>
(2)两条sql进行查询
mapper.xml中
其中association 多加了两个属性
column:所对应的外键字段名称(数据库字段)把第一次查询的某一个作为第二次查询的值
select:把column列值交给select这个查询语句,填的是第二个查询语句的id,使用另一个查询封装的结果
第二条sql中就不能写resultMap了,写resultType
<resultMap id="classMap" type="Clazz">
<id column="c_id" property="cid"/>
<result column="c_name" property="cname"/>
<!-- 一对一关系-->
<!-- column把第一次查询的某一个作为第二次查询的值
select把column列值交给select这个查询语句
-->
<association property="teacher" javaType="com.zz.entity.Teacher" column="teacher_id" select="findTeacherById" >
<id column="t_id" property="tid"/>
<result column="t_name" property="tName"/>
</association>
</resultMap>
<select id="findClassById" resultMap="classMap" >
select * from class where c_id=#{cid}
</select>
<select id="findTeacherById" resultType="com.zz.entity.Teacher">
select t_id tid ,t_name tName from teacher where t_id=#{tid}
</select>
一对多
数据库表student
CREATE TABLE student(
s_id INT PRIMARY KEY AUTO_INCREMENT,
s_name VARCHAR(20),
class_id INT
);
INSERT INTO student(s_name, class_id) VALUES('xs_A', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_B', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_C', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_D', 2);
INSERT INTO student(s_name, class_id) VALUES('xs_E', 2);
INSERT INTO student(s_name, class_id) VALUES('xs_F', 2);
要求 根据班级id查询班级信息以及该班级下所有的学生信息。
Student 实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private Integer sid;
private String sName;
private String classId;
}
mapper.xml中
collection 表示一对多
collection 里面的property代表映射数据库列的字段或属性(代表实体类字段)
collection 里面的ofType代表返回类型,跟resultType一个意思
<!-- 一对多 -->
<resultMap id="classMap" type="com.zz.entity.Clazz">
<id column="c_id" property="cid"/>
<result column="c_name" property="cname"/>
<!-- 多对一的映射-->
<association property="teacher" javaType="com.zz.entity.Teacher">
<id column="t_id" property="tid"/>
<result column="t_name" property="tname"/>
</association>
<!-- 一对多-->
<!-- ofType/表示集合的泛型-->
<collection property="student" ofType="com.zz.entity.Student">
<id column="s_id" property="sid"/>
<result column="s_name" property="sname"/>
</collection>
</resultMap>
<!-- 只要使用联表查询,必须使用resultMap-->
<select id="findClassById" resultMap="classMap">
SELECT * from class c,teacher t ,student s where c.teacher_id=t.t_id
and c.c_id=s.class_id and c.c_id=1
</select>
xml碰到特殊字符如何处理
(1)可以使用转移字符
(2)使用CDATA
<![CDATA[sql]]>
mapper.xml中
<!-- 查询cid在区间的范围-->
<select id="findBetweenById" resultMap="classMap">
<![CDATA[select * from class where c_id>=#{min} and c_id<=#{max}]]>
</select>