一、可以优化的几个地方:
1、将数据库连接的设置放在一个配置文件中
db.properties
jdbc.driverName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///test jdbc.username=root jdbc.password=root
在mybatis配置文件中引用db.properties
<?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 resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
</configuration>
2、给实体类起别名,简化映射文件中对实体类引用的写法
别名在mybatis配置文件中设置
<?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> <!-- 给实体类起别名--> <typeAliases> <!-- 1、单独给一个实体类起别名,该例的别名就是“s”--> <!-- <typeAlias type="com.fy.bbb.entity.SalGrade" alias="s"></typeAlias>--> <!-- 2、给整个包起别名,类的别名就是类名 --> <package name="com.fy.bbb.entity"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/SalGradeMapper.xml"></mapper> </mappers> </configuration>
配置文件中对别名的使用
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.fy.bbb.dao.SalGradeDao"> <select id="getAll" resultType="s"> select * from salgrade </select> </mapper>
3、解决实体类中的字段和数据表字段不对应的问题
①、给数据库查询语句起别名,别名和实体类字段名相同
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fy.bbb.dao.SalGradeDao">
<!-- 解决java实体类字段和数据库字段不相同的问题-->
<!-- 1、给sql语句中的字段起别名-->
<select id="getAll" resultType="com.fy.bbb.entity.SalGrade">
select grade as g from salgrade
</select>
</mapper>
②、在配置文件中使用resultMap,将数据库表字段和实体类属性一 一对应。resultMap还是连表查询必须要用的
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.fy.bbb.dao.SalGradeDao"> <!-- 解决java实体类字段和数据库字段不相同的问题--> <!-- 2、使用resultMap--> <resultMap id="baseMap" type="com.fy.bbb.entity.SalGrade"> <!-- id标签中映射主键列 column中写数据库字段 property中写java实体类的属性--> <id column="id" property="id"></id> <!-- result标签映射其他列--> <result column="grade" property="grade"></result> <result column="losal" property="losal"></result> <result column="hisal" property="hisal"></result> </resultMap> <select id="getAll" resultType="com.fy.bbb.entity.SalGrade"> select * from salgrade </select> </mapper>
4、加入日志
步骤:
①、导入jar包
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
②、写配置文件 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
二、连表查询
注:使用mybatis查询时,我们要指定resultMap或者resultType。连表查询时就不是一个单一的实体类就能接收数据了,所以要在实体类之间相互引用
准备表数据:class表和teacher表
CREATE TABLE teacher( t_id INT PRIMARY KEY AUTO_INCREMENT, t_name VARCHAR(20) ); 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);
①、多对一:多个职员对应一个级别,此时就要将级别表实体类引入到职员表的实体类中
实体类:
class:班级实体类
@Data @NoArgsConstructor @AllArgsConstructor public class Clazz { // private int cid; private String cname; private Teacher teacher;//该班级对应的老师信息 }
teacher:老师实体类
@Data @AllArgsConstructor @NoArgsConstructor public class Teacher { private int tid; private String tname; }
映射文件:classMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace必须和接口的全路径匹配--> <mapper namespace="com.ykq.dao.ClazzDao"> <!--联表查询得到的结果--> <resultMap id="ClazzMap" type="com.ykq.entity.Clazz"> <id column="c_id" property="cid"/> <result column="c_name" property="cname"/> <!--association多对一的映射 javaType:表示属性名对应的java实体类类型 --> <association property="teacher" javaType="com.ykq.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> </mapper>
第二种写法,将sql语句分开写,改动仅是映射文件。
先查询班级,再查班级中对应的老师,两次查询
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace必须和接口的全路径匹配--> <mapper namespace="com.ykq.dao.ClazzDao"> <!--两次查询得到结果--> <resultMap id="ClazzMap" type="com.ykq.entity.Clazz"> <id column="c_id" property="cid"/> <result column="c_name" property="cname"/> <!--column:把第一次查询的某一列作为第二次查询的值,自动赋值 select:指定第二次要执行的sql --> <association property="teacher" javaType="com.ykq.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="ClazzMap"> select * from class where c_id=#{cid} </select> <select id="findTeacherById" resultType="com.ykq.entity.Teacher"> select t_id tid,t_name tname from teacher where t_id=#{tid} </select> </mapper>
②、一对多:一个班级对应多个学生,应为是多个学生,所以要把学生实体类引用班级实体类中时要用集合的方式
创建学生表:
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);
Student:学生实体类
@AllArgsConstructor @NoArgsConstructor @Data public class Student { private int sId; private String sname; }
class:班级实体类
@Data @NoArgsConstructor @AllArgsConstructor public class Clazz { // private int cid; private String cname; private Teacher teacher;//该班级对应的老师信息 //表示该班级下所有的学生信息 private List<Student> students; }
教师表不动。
映射文件:classMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace必须和接口的全路径匹配--> <mapper namespace="com.ykq.dao.ClazzDao"> <!--联表查询得到的结果--> <resultMap id="ClazzMap" type="com.ykq.entity.Clazz"> <id column="c_id" property="cid"/> <result column="c_name" property="cname"/> <!--association多对一的映射 javaType:表示属性名对应的java实体类类型 --> <association property="teacher" javaType="com.ykq.entity.Teacher"> <!--该属性的名称与字段的对应关系--> <id column="t_id" property="tid"/> <result column="t_name" property="tname"/> </association> <!--ofType:表示集合的泛型--> <!--collection:一对多的配置使用collection--> <collection property="students" ofType="com.ykq.entity.Student"> <id column="s_id" property="sId"/> <result column="s_name" property="sname"/> </collection> </resultMap> <!--只要使用联表查询 必须使用resultMap--> <select id="findClassByid" resultMap="ClazzMap"> 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 and c.c_id <=1 </select> </mapper>
三、xml碰见特殊字符的处理
例:再sql语句中使用小于“<”就会出问题
解决方法:
①可以使用转义字符
②、使用CDATA
<select id="findClassBetweenIds" resultMap="ClazzMap">
<![CDATA[select * from class where c_id >=#{minId} and c_id <=#{maxId}]]>
</select>