目录
一、MyBatis基础配置
1. MyBatis配置文件
- 功能:构建SqlSessionFactory的依据。
- 意义:MyBatis最为核心的内容,对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> <!-- 和spring整合后 environments配置将废除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理 --> <transactionManager type="JDBC" /> <!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/myhomework03?serverTimezone=GMT" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/zkt/mapper/student.xml" /> </mappers> </configuration>
- 驱动类 JDBC 驱动类的名称
- URL 所连接数据库的 URL
- 用户名 所连接数据库的用户名
- 密码 所连接数据库的密码
配置文件的层级结构
2. < configuration>元素
功能:标识配置文件的起始,所有配置信息都存放在这里。
3. < enviroments>元素
功能:配置数据库环境信息,注册数据源, 配置数据库事务。
- <enviroment>:单个环境信息的标识
- <transactionManager>:配置数据库事务;
数据库事务
●JDBC 使用 JDBC 的事务管理机制,就 是利用 java.sql.Connection 对 象完成对事务的提交;
●MANAGED 使用MANAGED 的事务管理机 制,这种机制MyBatis 自身不 会去实现事务管理,而是让程序 的容器(JBOSS,WebLogic)来 实现对事务的管理;
●自定义 由使用者自定义数据库事务的管 理方式,适用于特殊应用。
- <dataSource>:配置环境信息中数据源连接的信息。
数据源
UNPOOLED 非连接池的数据源
POOLED 连接池的数据源
JNDI JNDI的数据源
自定义数据源 其他类型数据源
- <property>:配置环境信息的属性;
4. < properties>元素
功能:配置属性的元素,可以在配置文件的上下文中使用 该属性。
properties 配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/myhomework03?serverTimezone=GMT jdbc.username=root jdbc.password=123456
程序参数传递
property 子元素
<property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" />
使用:
将jdbc.properties 放到src目录下
使用建议
- 不要使用混合方式,以避免管理混乱
- 首选的方式是 Properties 文件方式
- 如存在加密或者安全访问的问题,使用 第二种方式,为日后统一管理提供方便
5. < typeAliases>元素
别名 sqlMapper.xml 中用
Mybatis内部支持的别名:
别名和大小写无关
别名 映射的类型 别名 映射的类型 _byte byte byte Byte _long long long Long _short short short Short _int int integer Integer _integer int double Double _double double float Float _float float boolean Boolean _boolean boolean date Date string String decimal BigDecimal bigdecimal BigDecimal map Map
功能:我们使用Mybatis 需要将查询的虚拟表映射为java中的实体类的对象,就需 要让Mybatis知道这些我们自定义的“类型”。
在主配置文件中进行配置
<typeAliases> <package name="com.zkt.bean"/> </typeAliases>
在StudentMapper.xml 中可以使用类名
别名和大小写无关
6. < mappers>元素
功能:用来在MyBatis初始化的时候引入映射器。
<mappers>层次结构
用第三种方法
最终的主配置文件:
<?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"> </properties> <typeAliases> <package name="com.zkt.bean"/> </typeAliases> <!-- 和spring整合后 environments配置将废除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理 --> <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> <!-- <mapper resource="com/zkt/mapper/StudentMapper.xml" /> --> <package name="com.zkt.mapper"/> </mappers> </configuration>
把接口和sqlmapper.xml放到一个包下
同包同名同路径
注册指定包下的所有mapper接口
这样就可以将mapper包下的sqlMapper.xml文件读取到
面试题
为什么不能用方法的重载
使用了动态代理
要求了方法名要和id一致
又因为mybatis 要求id不允许重复
所以不能实现方法的重载
二、动态代理
在接口中有方法的返回值定义,参数的定义,方法名,在sqlMapper.xml 中也对应这接口给予了赋值, 这时候dao的实现类就显得多余,这是Mybatis可以帮助我们自动产生实现类,并可以调取方法得到结 果,这就是Mybatis的mapper动态代理
动态代理的规范
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接 口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
- 1. Mapper.xml文件中的namespace与mapper接口的类路径相同。
- 2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
- 3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
- 4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
动态代理:
- 1. 接口中的方法名要和SqlSession中的id一致
- 2. 接口中的入参 要和 parameterType 类型一致
- 3. 接口中的方法的出参 要和 resultType 类型一致
- 4. 接口和sqlMapper 同包
- 5. 接口和sqlMapper 同名
- 6. 接口类路径 和 sqlMapper 的namesapce 一致
使用动态代理
使用SqlSession的方法getMapper() 让Mybatis自动生成对应接口的实现对象。
SqlSession sqlSession = DaoUtil.getSqlSession(); //动态代理 // 1. 接口中的方法名要和SqlSession中的id一致 // 2. 接口中的入参 要和 parameterType 类型一致 // 3. 接口中的方法的出参 要和 resultType 类型一致 // 4. 接口和sqlMapper 同包 // 5. 接口和sqlMapper 同名 // 6. 接口类路径 和 sqlMapper 的namesapce 一致 StudentMapper isd =sqlSession.getMapper(StudentMapper.class); List<Student> sList = isd.findAllStudent(); sList.forEach(System.out::println); DaoUtil.closeResource(sqlSession);
- selectOne和selectList :动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用 selectList方法,如果返回单个对象则调用selectOne方法。
- namespace: mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入 参数可以使用pojo包装对象或map对象,保证dao的通用性。
三、映射器
- 半自动化的体现 配置SQL 语句,体现了半自动化 和灵活性。
- ORM的体现 对象关系映射的实现,数据库表 和POJO 类的映射关系。
1. 映射器与接口
映射器配置文件和接口绑定:配置文件名对应接口名,id 属性值对应方法名。
2. 映射器的引入
3. 映射器的组成
<sql>:提取sql代码 引用sql标签实现sql语句
<parameterMap>:参数的映射(已经弃用)
四、select 元素
语法:
语法规则: < select 属性=“值”>查询类SQL语句</ select >
输出简单类型: 定义接口方法:
属性 说明 id 唯一标识,接口中的方法名; parameterType 参数的类型; resultType 结果的类型; resultMap 复杂的结果集映射关系; //学生表中一共有多少学生 public int countStudent();
在StudentMapper.xml中写对应标签和sql语句
<select id="countStudent" resultType="int"> select count(*) from student </select>
测试:
StudentMapper isd =sqlSession.getMapper(StudentMapper.class); int c = isd.countStudent(); System.out.println("一共有"+c+"个学生"); DaoUtil.closeResource(sqlSession);
参数传递
- XML 文件中:配置文件中利用parameterType 属性设置参数类型,利用 #{}设置参数的使用及位置。
- 接口中:接口中,按照方法的入参方式指定参数类型和参数名称。
如果条件有> < >= <= 可以使用转义字符进行代替:
StudentMapper.xml
符号 小于 小于等于 大于 大于等于 和 单引号 双引号 原符号 < <= > >= & ' " 替换符号 < <= > >= & ' " <select id="findStudentxiaoyuNum" resultType="Student" parameterType="int"> select * from student where sid < #{v} </select>
StudentMapper.java
//学生标号小于num public List<Student> findStudentxiaoyuNum(int num);
测试:
StudentMapper isd =sqlSession.getMapper(StudentMapper.class); List<Student> sList = isd.findStudentxiaoyuNum(5); sList.forEach(System.out::println); DaoUtil.closeResource(sqlSession);
多个参数传递
方法1:JavaBean 方式
StudentMapper.xml
<select id="findStudentBySsexAndClassid" resultType="Student" parameterType="Student"> select * from student where ssex= #{ssex} and classid= #{classid} </select>
StudentMapper.java
//多参 --->增删改查 //1. 对象 public List<Student> findStudentBySsexAndClassid(Student s);
测试:
StudentMapper isd =sqlSession.getMapper(StudentMapper.class); Student s = new Student(); s.setSsex("男"); s.setClassid(1); System.out.println(isd.findStudentBySsexAndClassid(s)); DaoUtil.closeResource(sqlSession);
方法2:Map 方式
耦合度太高
StudentMapper.xml
<select id="findStudentPageByMap" resultType="Student" parameterType="map"> select * from student limit #{wz},#{bc} </select>
StudentMapper.java
//分页查看学生信息 limit 位置 ,步长 Map //2.Map public List<Student> findStudentPageByMap(Map<String, Integer> map);
测试:
StudentMapper isd =sqlSession.getMapper(StudentMapper.class); Map<String, Integer> map= new HashMap<String, Integer>(); map.put("wz", (1-1)*3); map.put("bc", 3); List<Student> sList = isd.findStudentPageByMap(map); sList.forEach(System.out::println); DaoUtil.closeResource(sqlSession);
方法3:arg0 方式
StudentMapper.xml
<select id="findStudentBySsexAndClassidArgs" resultType="Student" > select * from student where ssex= #{arg0} and classid= #{arg1} </select>
StudentMapper.java
//3.arg0... 尽量不使用 会失效 public List<Student> findStudentBySsexAndClassidArgs(String sex,int classid);
测试:
StudentMapper isd =sqlSession.getMapper(StudentMapper.class); List<Student> sList = isd.findStudentBySsexAndClassidArgs("女", 2); sList.forEach(System.out::println); DaoUtil.closeResource(sqlSession);
方法4:param1方式
StudentMapper.xml
<select id="findStudentBySsexAndClassidParams" resultType="Student" > select * from student where ssex= #{param1} and classid= #{param2} </select>
StudentMapper.java
//4.param1... public List<Student> findStudentBySsexAndClassidParams(String sex,int classid);
测试:
StudentMapper isd =sqlSession.getMapper(StudentMapper.class); List<Student> sList = isd.findStudentBySsexAndClassidParams("女", 2); sList.forEach(System.out::println); DaoUtil.closeResource(sqlSession);
五、insert 元素
语法:
语法规则: < insert 属性=“值”>新增类SQL语句</ insert >
属性 说明 id 唯一标识,接口中的方法名; parameterType 参数的类型; keyProperty(属性名) 表示以哪个列作为属性的主键,不能和keyColumn同时使用; keyColumn(字段名) 指明哪一列是主键,不能和keyProperty同时使用; useGeneratedKeys 使用JDBC的getGeneratedKeys方式来取有数据库内部生成的主键;
主键回填
功能:当主键在数据库中为自增字段时,新增成功后,回填主键。
StudentMapper.xml
<!-- 主键回填 useGeneratedKeys="true" 开启主键回填 keyProperty="sid" 把主键数据回填给对象的属性 --> <insert id="addStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="sid"> insert into student(sname,birthday,ssex,classid) values(#{sname},#{birthday},#{ssex},#{classid}) </insert>
StudentMapper.java
//新增 public int addStudent(Student s);
测试:
StudentMapper isd =sqlSession.getMapper(StudentMapper.class); //添加学生 --> 添加该学生的入学成绩 Student s = new Student(); s.setSsex("男"); s.setClassid(1); s.setSname("zkt77"); s.setBirthday(new Date()); System.out.println("添加前"+s); int ret =isd.addStudent(s); System.out.println("添加后"+s); if (ret>0) { System.out.println("添加成功"); sqlSession.commit(); }else { System.out.println("添加失败"); sqlSession.rollback(); } DaoUtil.closeResource(sqlSession);
示例所有代码
Student.java
public class Student { //属性 对应 数据库中的字段 ---名字一致 类型一致 //长像相似就行 private int sid; private String sname; private Date birthday; private String ssex; private int classid; //1:1外部属性 private Banji bj; get/set 方法 构造方法省略。。。 }
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.zkt.mapper.StudentMapper"> <select id="findAllStudent" resultType="student"> select * from student </select> <select id="countStudent" resultType="int"> select count(*) from student </select> <select id="findStudentSname" resultType="String"> select sname from student </select> <select id="findStudentxiaoyuNum" resultType="Student" parameterType="int"> select * from student where sid < #{v} </select> <select id="findStudentBySsexAndClassid" resultType="Student" parameterType="Student"> select * from student where ssex= #{ssex} and classid= #{classid} </select> <select id="findStudentPageByMap" resultType="Student" parameterType="map"> select * from student limit #{wz},#{bc} </select> <select id="findStudentBySsexAndClassidArgs" resultType="Student"> select * from student where ssex= #{arg0} and classid= #{arg1} </select> <select id="findStudentBySsexAndClassidParams" resultType="Student"> select * from student where ssex= #{param1} and classid= #{param2} </select> <select id="findStudentBySid" resultType="Student" parameterType="int"> select * from student where sid = #{v} </select> <!-- 主键回填 useGeneratedKeys="true" 开启主键回填 keyProperty="sid" 把主键数据回填给对象的属性 --> <insert id="addStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="sid"> insert into student(sname,birthday,ssex,classid) values(#{sname},#{birthday},#{ssex},#{classid}) </insert> <!-- 多表 所有字段都要写映射关系 --> <resultMap type="Student" id="stu_class_Map"> <result column="sid" property="sid" /> <result column="sname" property="sname" /> <result column="birthday" property="birthday" /> <result column="ssex" property="ssex" /> <result column="classid" property="classid" /> <!--1:1 关系 --> <association property="bj"> <result column="classid" property="classid" /> <result column="classname" property="classname" /> </association> </resultMap> <select id="findStudentAndClass" resultMap="stu_class_Map"> select * from student left join class on student.classid=class.classid </select> <delete id="deleteStudent" parameterType="int"> delete from student where sid = #{v} </delete> <update id="updateStudent" parameterType="Student"> update student set sname = #{sname}, birthday = #{birthday}, ssex = #{ssex}, classid = #{classid} where sid = #{sid} </update> </mapper>
StudentMapper.java
package com.zkt.mapper; import java.util.List; import java.util.Map; import com.zkt.bean.Student; public interface StudentMapper { // 新增 public int addStudent(Student s); // 修改 public int updateStudent(Student s); // 删除 public int deleteStudent(int sid); // 查询 // 单查 public Student findStudentBySid(int sid); // 全查 public List<Student> findAllStudent(); // 学生表中一共有多少学生 public int countStudent(); // 获取学生表中所有学生的姓名 public List<String> findStudentSname(); // 学生标号小于num public List<Student> findStudentxiaoyuNum(int num); // 多参 --->增删改查 // 1. 对象 public List<Student> findStudentBySsexAndClassid(Student s); // 分页查看学生信息 limit 位置 ,步长 Map // 2.Map public List<Student> findStudentPageByMap(Map<String, Integer> map); // 3.arg0... 尽量不使用 会失效 public List<Student> findStudentBySsexAndClassidArgs(String sex, int classid); // 4.param1... public List<Student> findStudentBySsexAndClassidParams(String sex, int classid); // 查询学生和对应的信息 public List<Student> findStudentAndClass(); }
测试:
package com.zkt.test; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.ibatis.session.SqlSession; import com.zkt.bean.Student; import com.zkt.dao.DaoUtil; import com.zkt.mapper.StudentMapper; public class Test { public static void main(String[] args) { SqlSession sqlSession = DaoUtil.getSqlSession(); // 动态代理 // 1. 接口中的方法名要和SqlSession中的id一致 // 2. 接口中的入参 要和 parameterType 类型一致 // 3. 接口中的方法的出参 要和 resultType 类型一致 // 4. 接口和sqlMapper 同包 // 5. 接口和sqlMapper 同名 // 6. 接口类路径 和 sqlMapper 的namesapce 一致 StudentMapper isd = sqlSession.getMapper(StudentMapper.class); // int c = isd.countStudent(); // System.out.println("一共有"+c+"个学生"); // List<String> nameList = isd.findStudentSname(); // nameList.forEach(System.out::println); // List<Student> sList = isd.findStudentxiaoyuNum(5); // sList.forEach(System.out::println); // Student s = new Student(); // s.setSsex("男"); // s.setClassid(1); // System.out.println(isd.findStudentBySsexAndClassid(s)); // Map<String, Integer> map= new HashMap<String, Integer>(); // map.put("wz", (1-1)*3); // map.put("bc", 3); // List<Student> sList = isd.findStudentPageByMap(map); // sList.forEach(System.out::println); // List<Student> sList = isd.findStudentBySsexAndClassidArgs("女", 2); // List<Student> sList = isd.findStudentBySsexAndClassidParams("女", 2); // sList.forEach(System.out::println); // 添加学生 --> 添加该学生的入学成绩 Student s = new Student(); s.setSsex("男"); s.setClassid(1); s.setSname("zkt77"); s.setBirthday(new Date()); System.out.println("添加前" + s); int ret = isd.addStudent(s); System.out.println("添加后" + s); if (ret > 0) { System.out.println("添加成功"); sqlSession.commit(); } else { System.out.println("添加失败"); sqlSession.rollback(); } DaoUtil.closeResource(sqlSession); // Student s = isd.findStudentBySid(5); // System.out.println(s); // Student s1 =new Student(); // s1.setSname("刘备"); // s1.setSsex("男"); // s1.setBirthday(new Date()); // s1.setClassid(2); // int ret =isd.addStudent(s1); // if (ret>0) { // System.out.println("添加成功"); // }else { // System.out.println("添加失败"); // } // int ret=isd.deleteStudent(13); // if (ret>0) { // System.out.println("删除成功"); // }else { // System.out.println("删除失败"); // } // Student s2 =new Student(); // s2.setSid(9); // s2.setSname("张飞"); // s2.setSsex("女"); // s2.setBirthday(new Date()); // s2.setClassid(1); // int ret =isd.updateStudent(s2); // if (ret>0) { // System.out.println("修改成功"); // }else { // System.out.println("修改失败"); // } } }
六、update 元素和delete 元素
实现方式同上
update 元素
语法:
语法规则: < update 属性=“值”>查询类SQL语句</ update >
属性 说明 id 唯一标识,接口中的方法名; parameterType 参数的类型;
delete 元素
语法:
语法规则: < delete 属性=“值”>查询类SQL语句</ delete >
属性 说明 id 唯一标识,接口中的方法名; parameterType 参数的类型;
七、resultMap 元素
- 定义映射规则 ORM 的特性,POJO 类和数据 库的映射关系;
- 级联操作 多表存在主外键关系时,主表和 从表之间的关联操作;
- 类型转换 数据库字段的类型和POJO 类 属性的类型转换。
resultMap 元素的结构
<resultMap> <constructor> <idArg /> <arg /> </constructor> <id /> <result /> <association /> <collection /> <discriminator> <case /> </discriminator> </resultMap> <constructor> 用于配置构造方法的元素。 <id> 标识主键列,允许多个主键。 <result> POJO到SQL列名的映射关系。
使用POJO 存储结果集
练习:
表的结构: create table schoolmaster( smid int PRIMARY KEY auto_increment, sm_name varchar(10) , smsex varchar(2) ); insert into schoolmaster(sm_name,smsex) values('老刘','男');
表名和字段名不一致
如果没有做映射处理
我们发现获取表名不一样没有问题 但是字段名不一样会拿不到值
映射处理后
SMaster.java
public class SMaster { private int smid; private String smname; private String smsex; get/set 方法 构造方法省略。。。 }
SMasterMapper.java
public interface SMasterMapper { //新增 public int addSm(SMaster sm); //查询 public List<SMaster> findAllSm(); }
SMasterMapper.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.zkt.mapper.SMasterMapper"> <insert id="addSm" parameterType="SMaster"> insert into schoolmaster(sm_name,smsex) values(#{smname},#{smsex}) </insert> <!-- 单表查询 只写映射不上的 --> <resultMap type="SMaster" id="smMap"> <result column="sm_name" property="smname" /> </resultMap> <select id="findAllSm" resultMap="smMap"> select * from schoolmaster </select> </mapper>
测试:
public static void main(String[] args) { SqlSession sqlSession =DaoUtil.getSqlSession(); SMasterMapper smMapper =sqlSession.getMapper(SMasterMapper.class); SMaster sm = new SMaster(); sm.setSmname("zkt"); sm.setSmsex("男"); int ret=smMapper.addSm(sm); if (ret>0) { System.out.println("添加成功"); sqlSession.commit(); }else { System.out.println("添加失败"); sqlSession.rollback(); } // List<SMaster> sList = smMapper.findAllSm(); // sList.forEach(System.out::println); DaoUtil.closeResource(sqlSession); }
注意: 单表查询 只写映射不上的
八、多表联查
级联(cascade),是指多个对象之间的映射关系,建立数据之间的级联关系提高管理效率
- 一对一 :一个对象对应唯一的对象, 举例:中国公民和身份证;
- 一对多 :一个对象对应多个对象, 举例:班级和学生;
- 多对多 :多个对象对应多个对象, 举例:公司角色和公司员工
一对一
一对一级联步骤
- 创建关联POJO:一对一级联时,以对象方式存 储关联关系;
- 创建映射器:创建对应的映射器;
- 级联映射:利用 <association>元素完成一对一级联;
- 验证:编写测试类验证级联关系;
首先在实体类中添加级联表的对象:
Student.java
public class Student { //属性 对应 数据库中的字段 ---名字一致 类型一致 //长像相似就行 private int sid; private String sname; private Date birthday; private String ssex; private int classid; //1:1外部属性 private Banji bj; get/set 方法 构造方法省略。。。 }
StudentMapper.xml
<!-- 多表 所有字段都要写映射关系 --> <resultMap type="Student" id="stu_class_Map"> <result column ="sid" property ="sid"/> <result column ="sname" property ="sname"/> <result column ="birthday" property ="birthday"/> <result column ="ssex" property ="ssex"/> <result column ="classid" property ="classid"/> <!--1:1 关系 --> <association property="bj"> <result column ="classid" property ="classid"/> <result column ="classname" property ="classname"/> </association> </resultMap> <select id="findStudentAndClass" resultMap="stu_class_Map"> select * from student left join class on student.classid=class.classid </select>
StudentMapper.java
//查询学生和对应的信息 public List<Student> findStudentAndClass();
测试:
public class Test04 { public static void main(String[] args) { SqlSession sqlSession =DaoUtil.getSqlSession(); StudentMapper stuMapper =sqlSession.getMapper(StudentMapper.class); List<Student> sList = stuMapper.findStudentAndClass(); sList.forEach(System.out::println); DaoUtil.closeResource(sqlSession); } }
一对多
一对多级联步骤
- 创建”一“方POJO:以集合的形式级联“多”方对象
- 创建“多”方对象:创建“多”方的POJO 对象
- 创建映射器:创建对应的映射器
- 实现一对多级联:利用collection 元素实现一对多的级联
- 测试:编写测试文件测试一对多级联
首先在实体类中添加级联表的对象list集合:
Banji.java
public class Banji { private int classid; private String classname; //1:N 外部属性 private List<Student> sList; get/set 方法 构造方法省略。。。 }
BanjiMapper.java
public interface BanjiMapper { public List<Banji> findBanjiAndStudent(); }
BanjiMapper.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.zkt.mapper.BanjiMapper"> <resultMap type="Banji" id="class_stu_Map"> <result column="classid" property="classid" /> <result column="classname" property="classname" /> <!--1:N --> <collection property="sList" ofType="student"> <result column="sid" property="sid" /> <result column="sname" property="sname" /> <result column="birthday" property="birthday" /> <result column="ssex" property="ssex" /> <result column="classid" property="classid" /> </collection> </resultMap> <select id="findBanjiAndStudent" resultMap="class_stu_Map"> select * from class left join student on class.classid=student.classid </select> </mapper>
测试:
public class Test05 { public static void main(String[] args) { SqlSession sqlSession = DaoUtil.getSqlSession(); BanjiMapper bjMapper = sqlSession.getMapper(BanjiMapper.class); List<Banji> sList = bjMapper.findBanjiAndStudent(); sList.forEach(System.out::println); DaoUtil.closeResource(sqlSession); } }
多对多
换种思路 以 成绩表为主表 对其他俩个表进行联查
bean下
Course.java
public class Course { private int cid; private String cname; private int tid; get/set 方法 构造方法省略。。。 }
Sc.java
public class Sc { private int sid; private int cid; private double score; // 外部属性 private Student stu; private Course cou; get/set 方法 构造方法省略。。。 }
mapper下
ScMapper.java
public interface ScMapper { public List<Sc> findAllScAndStudentAndCourse(); }
ScMapper.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.zkt.mapper.ScMapper"> <resultMap type="Sc" id="sc_stu_cou_Map"> <result column="sid" property="sid"/> <result column="cid" property="cid"/> <result column="score" property="score"/> <association property="stu"> <result column="sid" property="sid"/> <result column="sname" property="sname"/> <result column="birthday" property="birthday"/> <result column="ssex" property="ssex"/> <result column="classid" property="classid"/> </association> <association property="cou"> <result column="cid" property="cid"/> <result column="cname" property="cname"/> <result column="tid" property="tid"/> </association> </resultMap> <select id="findAllScAndStudentAndCourse" resultMap="sc_stu_cou_Map"> select * from sc inner join student on sc.sid = student.sid inner join course on course.cid = sc.cid </select> </mapper>
测试:
public class Test06 { public static void main(String[] args) { SqlSession sqlSession = DaoUtil.getSqlSession(); ScMapper scmapper = sqlSession.getMapper(ScMapper.class); List<Sc> sclist = scmapper.findAllScAndStudentAndCourse(); for (Sc sc : sclist) { System.out.println(sc.getStu().getSname() + "-" + sc.getCou().getCname() + "-" + sc.getScore()); } DaoUtil.closeResource(sqlSession); } }
级联的缺陷
- 性能缺陷 级联操作会降低性能, 增加程序的执行时间;
- 复杂度缺陷 关联较多造成复杂度的 增加,不利于他人的理 解和维护;
使用建议
1、根据实际情况增加级联关系
2、多层关联式,建议超过三层关联时尽量少用级联
标签:insert,StudentMapper,多表,元素,List,System,sqlSession,println,public From: https://blog.csdn.net/qq_52897007/article/details/140118002