打包⽅式:jar
依赖:mybatis依赖,mysql驱动依赖,junit依赖,logback依赖
配置⽂件:mybatis-config.xml、logback.xml、jdbc.properties
拷⻉⼯具类:SqlSessionUtil
1.准备数据1031.1创建数据库1033⼀一个班对应多个学习⽣。班级表:t_clazz。学⽣表:t_student
1.2创建pojo:Student、Clazz104
package com.powernode.mybatis.pojo;//实体类 学生 pojo 104/** * 学生信息 */public class Student { // Student是多方 private Integer sid; private String sname; private Clazz clazz; // Clazz是一方。 @Override public String toString() { return "Student{" + "sid=" + sid + ", sname='" + sname + '\'' + ", clazz=" + clazz + '}'; } public Clazz getClazz() { return clazz; } public void setClazz(Clazz clazz) { this.clazz = clazz; } public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Student(Integer sid, String sname) { this.sid = sid; this.sname = sname; } public Student() { }}
package com.powernode.mybatis.pojo;//实体类 班级 pojo 104import java.util.List;/** * 班级信息 */public class Clazz { private Integer cid; private String cname; public Clazz() { } public Clazz(Integer cid, String cname) { this.cid = cid; this.cname = cname; } public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } @Override public String toString() { return "Clazz{" + "cid=" + cid + ", cname='" + cname + '\'' + '}'; }}
2.多对一映射实体关系105
多对一:
多一方是:Student
一、方是:Clazz
2.1如何分为主表和副表?105原则:谁在前,谁是主表。
多对一:多在前,那么多就是主表。
一对多:一-在前,那么一-就是主表。
2.2多种⽅式,常⻅包括三种:106●第⼀种⽅式:⼀条SQL语句,级联属性映射。
●第⼆种⽅式:⼀条SQL语句,association。
●第三种⽅类型:两个SQL语句,分步查询。(这种。⽅式常⽤:优点⼀是可复⽤。优点⼆是⽀持懒加载。)
2.2.1第⼀种⽅式:⼀SQL语句,级联属性映射。106添加pojo类Student⼀个属性:Clazzclazz;表示学⽣相关班级对象。
@Test public void testselectById(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectById(1); System.out.println(student.getSid()); System.out.println(student.getSname()); System.out.println(student.getClazz().getCid()); System.out.println(student.getClazz().getCname()); //System.out.println(student); sqlSession.close(); }
<!--这个标签的作用是指定学生表t_stu和Java pojo Student的对应关系 多对一映射的第一种方式:SQL语句,级联属性映射。--> <resultMap id="studentResultMap" type="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <result property="clazz.cid" column="cid"/> <result property="clazz.cname" column="cname"/> </resultMap> <select id="selectById" resultMap="studentResultMap"> select s.sid,s.sname,c.cid,c.cname from t_stu s left join t_clazz c on s.cid = c.cid where s.sid = #{sid} </select>
2.2.2第⼆种⽅式:⼀条SQL语句,association。107
association:翻译为关联。Student对象与Clazz对象相关联。
property:提供要映射的POJO类属性名。
javaType:用于指定要映射的java类型。
<!--SQL语句,association。 107--> <resultMap id="studentResultMapAssociation" type="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <!-- association:翻译是相关的。-- association:翻译为关联。Student对象与Clazz对象相关联。 property:提供要映射的POJO类属性名。 javaType:用于指定要映射的java类型。 --> <association property="clazz" javaType="Clazz"> <id property="cid" column="cid"/> <result property="cname" column="cname"/> </association> </resultMap> <select id="selectByIdAssociation" resultMap="studentResultMapAssociation"> select s.sid,s.sname,c.cid,c.cname from t_stu s left join t_clazz c on s.cid = c.cid where s.sid = #{sid} </select>
//第二种方式 SQL语句,association 107 @Test public void testSelectByIdAssociation(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectByIdAssociation(4); System.out.println(student); sqlSession.close(); }
2.2.3第三种⽅类型:两个SQL语句,分步查询。108
(这种⽅式常⽤:优点⼀是可复⽤。优点⼆是⽀持懒加载。)
2.2.3.1第一步:108根据学生的身份证查询学生的所有信息。这些信息包含班级身份证(cid)
StudentMapper
/** * 这是多对一 * 分部查询第一步:先根据学生的sid查询学生的信息。 108 * @param sid * @return */ Student selectbyidstep1(Integer sid);
com.powernode.mybatis.test
StudentMapperTest
//分部查询第一步:先根据学生的sid查询学生的信息。 108 //分步查询第二步:根据cid获取班级信息。 108 @Test public void testelectbyidstep1(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectbyIdstep1(5); //System.out.println(student); // 懒加载 只要看学生的名字 109 System.out.println(student.getSname()); // 程序执行到此为止,我想看看班级的名字 //System.out.println(student.getClazz().getCname()); sqlSession.close(); }
2.2.3.2第⼆步:108
com.powernode.mybatis.mapper
在Clazmapper中⼝中添加⽅法
/** * 这是多对一 * 步骤2:根据cid获取班级信息。 108 * @param cid * @return */ Clazz selectbyidstep2(Integer cid);
clazmapper.xml⽂件中进⾏配置
<!--步骤2:根据cid获取班级信息。 108--> <select id=“selectbyIdstep2” resultType="Clazz"> select cid,cname from t_clazz where cid = #{cid} </select>
3.多对⼀延迟加载1093.1分步查询的优点:109
一是复用性增强。可重复使用。(大步拆成N多个小步骤。每一个小步骤都可以重复使用。)
第二:采用这种分步查询,可以充分利用其延迟加载/懒惰加载机制。
3.2什么是延迟加载(懒加载)?有什么用?109延迟加载的核心原理是:使用时执行查询句。不使用时不查询。
功能:提高性能。尽量不检查,或尽量少检查。提高效率。
3.2.如何在mybatis中打开延迟加载?109在association标签中添加fetchtype=lazy"
注:默认情况下未打开延迟加载。需要设置:fetchType="lazy"
在association标签中配置fetchtype=lazy“,是局部设置,只对当前association相关的sql语句起作用。
3.2.1.1延迟加载的全局开关109在实际开发中,大多数都需要使用延迟加载,因此建议启动所有延迟加载机制:
将全局配置添加到mybatis核心配置文件中:lazyLoadingEnabled=true
<settings> <!--全局开关延迟加载。不打开默认值false。 109--> <!--什么意思:只要有分步,都是延迟加载。--> <setting name="lazyLoadingEnabled" value="true"/> </settings>
实际开发中的模式:
打开全局延迟加载。
若某一步不需要延迟加载,请设置:fetchType="eager"
3.2.2例109要想⽀延迟加载,⾮通常很简单,只需在association标签中添加fetchtype=“lazy"即可。
修改Studentmapper.xml⽂件
我们现在只查询学习⽣修改测试程序:
<resultMap id="studentResultMapByStep" type="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <association property="clazz" select="com.powernode.mybatis.mapper.ClazzMapper.selectbyIdstep2 column="cid" fetchType="lazy"/> </resultMap> <select id=selectbyIdstep1 resultMap="studentResultMapByStep"> select sid,sname,cid from t_stu where sid = #{sid} </select>
@Test public void testelectbyidstep1(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectbyIdstep1(5); //System.out.println(student); // 懒加载 只要看学生的名字 109 System.out.println(student.getSname()); // 程序执行到此为止,我想看看班级的名字 109 //System.out.println(student.getClazz().getCname()); sqlSession.close(); }
假如后续需要使用⽤到学⽣班级名称,此时将执行⾏修改相关SQL语句的测试程序:
@Test public void testelectbyidstep1(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectbyIdstep1(5); //System.out.println(student); // 懒加载 只要看学生的名字 109 System.out.println(student.getSname()); // 程序执行到此为止,我想看看班级的名字 109 System.out.println(student.getClazz().getCname()); sqlSession.close(); }
通过以上执行⾏只有当使才能看到结果。⽤到了班名之后,才会执行⾏相关的sql语句,即延迟加载
4.一对多110 4.1⼀对多的实现通常包括两种实现⽅式:1114.1.1第⼀种⽅式:collection注意oftype,表示“集合类型”。
ClazzMapper.xml
<resultMap id="clazzResultMap" type="Clazz"> <id property="cid" column="cid"/> <result property="cname" column="cname"/> <!--一对多,这里是collection。--一对多,这里是collection。collection是集合的意思。111--> <!--ofType 该属性用于指定集合中的元素类型。--> <collection property="stus" ofType="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> </collection> </resultMap> <select id="selectByCollection" resultMap="clazzResultMap"> select c.cid,c.cname,s.sid,s.sname from t_clazz c left join t_stu s on c.cid = s.cid where c.cid = #{cid} </select>
ClazzMapperTest
//根据班级编号查询班级信息。 111 @Test public void testSelectByCollection(){ SqlSession sqlSession = SqlSessionUtil.openSession(); ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class); Clazz clazz = mapper.selectByCollection(1000); System.out.println(clazz); sqlSession.close(); }
4.1.2第⼆种⽅类型:分步查询112
第一步
ClazzMapper
/** * 这是一对多 * 分步查询。第一步:根据班级编号获取班级信息。 112 * @param cid 班级编号 * @return */ Clazz selectBystep1(Integer cid);
ClazzMapper.xml
<!--步骤1:根据班级cid获取班级信息。 112--> <resultMap id="clazzResultMapStep" type="Clazz"> <id property="cid" column="cid"/> <result property="cname" column="cname"/> <collection property="stus" select="com.powernode.mybatis.mapper.StudentMapper.selectByCidstep2 column="cid" fetchType="eager" /> </resultMap> <select id=selectbystep1 resultMap="clazzResultMapStep"> select cid,cname from t_clazz where cid = #{cid} </select>
ClazzMapperTest
//分步查询。第一步:根据班级编号获取班级信息。 112 @Test public void testselectbystep1(){ SqlSession sqlSession = SqlSessionUtil.openSession(); ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class); Clazz clazz = mapper.selectBystep1(1000); //System.out.println(clazz); // 只访问班级名称。 System.out.println(clazz.getCname()); // 只有在使用时才会执行第二步SQL //System.out.println(clazz.getStus()); sqlSession.close(); }
第二步
StudentMapper
/** * 这是一对多 * 第二步是分布查询 * 根据班级编号查询学生信息。 112 * @param cid * @return */ List<Student> selectByCidstep2(Integer cid);
StudentMapper.xml
<select id=selectbyCidstep2 resultType="Student"> select * from t_stu where cid = #{cid} </select>
5.代码汇总main中com.powernode.mybatis.mapperClazzMapper
package com.powernode.mybatis.mapper;import com.powernode.mybatis.pojo.Clazz;///班级接口 104public interface ClazzMapper { /** * 这是一对多 * 分步查询。第一步:根据班级编号获取班级信息。 112 * @param cid 班级编号 * @return */ Clazz selectBystep1(Integer cid); /** * 根据班级编号查询班级信息。 111 * @param cid * @return */ Clazz selectByCollection(Integer cid); /** * 这是多对一 * 步骤2:根据cid获取班级信息。 108 * @param cid * @return */ Clazz selectbyidstep2(Integer cid);}
StudentMapper
package com.powernode.mybatis.mapper;import com.powernode.mybatis.pojo.Student;import java.util.List;///学生接口 104public interface StudentMapper { /** * 这是一对多 * 第二步是分布查询 * 根据班级编号查询学生信息。 112 * @param cid * @return */ List<Student> selectByCidstep2(Integer cid); /** * 这是多对一 * 分部查询第一步:先根据学生的sid查询学生的信息。 108 * @param sid * @return */ Student selectbyidstep1(Integer sid); /** * SQL语句,association 107 * @param id * @return */ Student selectByIdAssociation(Integer id); /** * 第⼀种⽅式:⼀条SQL语句,级联属性映射。 106 * 根据id获取学生信息。 106 * 根据id获取学生信息。同时获取与学生相关的课堂信息。 106 * @param id 学生的id * @return 学生对象,但学生对象包含班级对象。 */ Student selectById(Integer id);}
ClazzMapper.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"><mapper namespace="com.powernode.mybatis.mapper.ClazzMapper"> <!--这是一对多 步骤1:根据班级cid获取班级信息。 112--> <resultMap id="clazzResultMapStep" type="Clazz"> <id property="cid" column="cid"/> <result property="cname" column="cname"/> <collection property="stus" select="com.powernode.mybatis.mapper.StudentMapper.selectByCidstep2 column="cid" fetchType="eager" /> </resultMap> <select id=selectbystep1 resultMap="clazzResultMapStep"> select cid,cname from t_clazz where cid = #{cid} </select> <resultMap id="clazzResultMap" type="Clazz"> <id property="cid" column="cid"/> <result property="cname" column="cname"/> <!--一对多,这里是collection。--一对多,这里是collection。collection是集合的意思。111--> <!--ofType 该属性用于指定集合中的元素类型。--> <collection property="stus" ofType="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> </collection> </resultMap> <select id="selectByCollection" resultMap="clazzResultMap"> select c.cid,c.cname,s.sid,s.sname from t_clazz c left join t_stu s on c.cid = s.cid where c.cid = #{cid} </select> <!--这是多对一步查询的第二步:根据cid获取班级信息。 108--> <select id=“selectbyIdstep2” resultType="Clazz"> select cid,cname from t_clazz where cid = #{cid} </select></mapper>
StudentMapper.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"><mapper namespace="com.powernode.mybatis.mapper.StudentMapper"> <!--这是一对多 步骤2:根据班级编号查询学生信息。--这是一对多 步骤2:根据班级编号查询学生信息。 108--> <select id=selectbyCidstep2 resultType="Student"> select * from t_stu where cid = #{cid} </select> <!-- 分步查询的优点: 一是增强复用性。可重复使用。(大步拆成N多个小步。每一个小步骤都可以重复使用。) 第二:采用这种分步查询,可以充分利用其延迟加载/懒惰加载机制。 什么是延迟加载(懒加载),有什么用? 延迟加载的核心原理是在使用时执行查询句。不用的时候不查询。 功能:提高性能。尽量不查,或者尽量少查。提高效率。 如何在mybatis中打开延迟加载? 在association标签中添加fetchtype=lazy" 注:默认情况下未打开延迟加载。需要设置:fetchType="lazy" 在association标签中配置fetchtype=lazy“,是局部设置,只对当前association相关的sql语句起作用。 在实际开发中,大多数都需要使用延迟加载,因此建议启动所有延迟加载机制: 将全局配置添加到mybatis核心配置文件中:lazyLoadingEnabled=true 实际开发中的模式: 打开全局延迟加载。 若某一步不需要延迟加载,请设置:fetchType="eager" --> <!--两个SQL语句,完成多对一步骤查询。--> <!--多对一是第一步:根据学生的身份证查询学生的所有信息。这些信息包含班级id(cid)--> <!--这个association中的select需要指定另一个sql语句的id--> <resultMap id="studentResultMapByStep" type="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <association property="clazz" select="com.powernode.mybatis.mapper.ClazzMapper.selectbyIdstep2 column="cid" fetchType="eager"/> </resultMap> <select id=selectbyIdstep1 resultMap="studentResultMapByStep"> select sid,sname,cid from t_stu where sid = #{sid} </select> <!--SQL语句,association。 107--> <resultMap id="studentResultMapAssociation" type="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <!-- association:翻译是相关的。-- association:翻译为关联。Student对象与Clazz对象相关联。 property:提供要映射的POJO类属性名。 javaType:用于指定要映射的java类型。 --> <association property="clazz" javaType="Clazz"> <id property="cid" column="cid"/> <result property="cname" column="cname"/> </association> </resultMap> <select id="selectByIdAssociation" resultMap="studentResultMapAssociation"> select s.sid,s.sname,c.cid,c.cname from t_stu s left join t_clazz c on s.cid = c.cid where s.sid = #{sid} </select> <!--这个标签的作用是指定学生表t_stu和Java pojo Student的对应关系 106 多对一映射的第一种方式:SQL语句,级联属性映射。--> <resultMap id="studentResultMap" type="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <result property="clazz.cid" column="cid"/> <result property="clazz.cname" column="cname"/> </resultMap> <select id="selectById" resultMap="studentResultMap"> select s.sid,s.sname,c.cid,c.cname from t_stu s left join t_clazz c on s.cid = c.cid where s.sid = #{sid} </select></mapper>
test中com.powernode.mybatis.testClazzMapperTest
package com.powernode.mybatis.test;import com.powernode.mybatis.mapper.ClazzMapper;import com.powernode.mybatis.pojo.Clazz;import com.powernode.mybatis.utils.SqlSessionUtil;import org.apache.ibatis.session.SqlSession;import org.junit.Test;public class ClazzMapperTest { //分步查询。第一步:根据班级编号获取班级信息。 112 @Test public void testselectbystep1(){ SqlSession sqlSession = SqlSessionUtil.openSession(); ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class); Clazz clazz = mapper.selectBystep1(1000); //System.out.println(clazz); // 只访问班级名称。 System.out.println(clazz.getCname()); // 只有在使用时才会执行第二步SQL //System.out.println(clazz.getStus()); sqlSession.close(); } //根据班级编号查询班级信息。 111 @Test public void testSelectByCollection(){ SqlSession sqlSession = SqlSessionUtil.openSession(); ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class); Clazz clazz = mapper.selectByCollection(1000); System.out.println(clazz); sqlSession.close(); }}
StudentMapperTest
package com.powernode.mybatis.test;import com.powernode.mybatis.mapper.StudentMapper;import com.powernode.mybatis.pojo.Student;import com.powernode.mybatis.utils.SqlSessionUtil;import org.apache.ibatis.session.SqlSession;import org.junit.Test;public class StudentMapperTest { //分部查询第一步:先根据学生的sid查询学生的信息。 108 //分步查询第二步:根据cid获取班级信息。 108 @Test public void testelectbyidstep1(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectbyIdstep1(5); //System.out.println(student); // 懒加载 只要看学生的名字 109 System.out.println(student.getSname()); // 程序执行到此为止,我想看看班级的名字 109 System.out.println(student.getClazz().getCname()); sqlSession.close(); } //第二种方式 SQL语句,association 107 @Test public void testSelectByIdAssociation(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectByIdAssociation(4); System.out.println(student); sqlSession.close(); } //第⼀种⽅式:⼀条SQL语句,级联属性映射。 ///根据id获取学生信息。 ///根据id获取学生信息。同时获取与学生相关的班级信息。 106 @Test public void testselectById(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectById(1); System.out.println(student.getSid()); System.out.println(student.getSname()); System.out.println(student.getClazz().getCid()); System.out.println(student.getClazz().getCname()); System.out.println(student); sqlSession.close(); }}
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 resource="jdbc.properties"/> <settings> <!--全局开关延迟加载。--全局开关延迟加载。false不打开默认值。 109--> <!--什么意思:只要有分步,都是延迟加载。--> <setting name="lazyLoadingEnabled" value="true"/> </settings> <typeAliases> <package name="com.powernode.mybatis.pojo"/> </typeAliases> <environments default="dev"> <environment id="dev"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <package name="com.powernode.mybatis.mapper"/> </mappers></configuration>
剩余的
pojo
utils
logback.xml
jdbc.properties
pom.xml
不做赘述