文章目录
- Mybatis 多对一 and 一对多查询详解
- 数据库
- 需求
- Mybatis代码
- 注意
Mybatis 多对一 and 一对多查询详解
数据库
员工表 t_emp
部门表 t_dept
CREATE TABLE `t_emp` (`emp_id` int NOT NULL AUTO_INCREMENT,`emp_name` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,`age` int DEFAULT NULL,`gender` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,`dept_id` int DEFAULT NULL,PRIMARY KEY (`emp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;CREATE TABLE `t_dept` (`dept_id` int NOT NULL AUTO_INCREMENT,`dept_name` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,PRIMARY KEY (`dept_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;INSERT INTO `t_emp` (`emp_id`, `emp_name`, `age`, `gender`, `dept_id`) VALUES (1, '张三', 20, '男', 1), (2, '李四', 22, '男', 2), (3, '王五', 23, '男', 3), (4, '赵六', 24, '男', 1);INSERT INTO `t_dept` (`dept_id`, `dept_name`) VALUES (1, 'A'), (2, 'B'), (3, 'C');
需求
多对一:员工表对应部门表
查询指定id的员工以及其对应的部门
一对多:部门表对应员工表
查询指定的部门以及其包含的员工
Mybatis代码
DeptMapper接口文件
package com.atguigu.mybatis.mapper;import com.ruanjian.pojo.Dept;
import com.ruanjian.pojo.Emp;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface DeptMapper {// 一对多查询// 查询部门表中的员工信息// 需要在部门类中添加员工的集合 private List<Emp> emps;Dept getDeptAndEmpById(@Param("deptId") Integer deptId);// 分步查询// 1.先查出指定id的部门信息,部门信息中有对应员工的dept_idDept getDeptAndEmpByStepOne(@Param("deptId") int deptId);// 2.再根据dept_id查出相对应的员工信息List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") int deptId);}
EmpMapper接口文件
package com.atguigu.mybatis.mapper;
import com.ruanjian.pojo.Dept;
import com.ruanjian.pojo.Emp;
import org.apache.ibatis.annotations.Param;public interface EmpMapper {// 多对一查询// 查询指定id员工以及该员工所对应的部门信息Emp getEmpAndDeptById(@Param("empId") Integer empId);Emp getEmpAndDeptById_association(@Param("empId") Integer empId);// 分步查询// 先从员工表中查询出指定id的员工的数据,该数据中有对应部门id// 再根据部门id从部门表中查询出对应的部门信息// 分步查询第一步Emp getEmpAndDeptByIdOne(@Param("empId") Integer empId);// 分步查询第二步Dept getEmpAndDeptByIdTwo(@Param("deptId") Integer deptId);
}
Dept类文件 部门实体类
package com.ruanjian.pojo;/*
员工对部门 是多对一,多对一是在多的那个类(员工类)中添加一个部门对象
部门对员工 是一对多,一对多是在一的那个类中(部门类)中添加一个员工集合对一 对的就是一个对象
对多 对的就是一个集合*/import java.util.List;// 部门实体类
public class Dept {private Integer deptId;private String deptName;private List<Emp> emps; // 添加的一个员工的集合public Dept() {}public Dept(Integer deptId, String deptName) {this.deptId = deptId;this.deptName = deptName;}public Integer getDeptId() {return deptId;}public void setDeptId(Integer deptId) {this.deptId = deptId;}public String getDeptName() {return deptName;}public void setDeptName(String deptName) {this.deptName = deptName;}public List<Emp> getEmps() {return emps;}public void setEmps(List<Emp> emps) {this.emps = emps;}@Overridepublic String toString() {return "Dept{" +"deptId=" + deptId +", deptName='" + deptName + '\'' +", emps=" + emps +'}';}
}
Emp类文件
员工实体类
package com.ruanjian.pojo;/*
员工对部门 是多对一,多对一是在多的那个类(员工类)中添加一个部门对象
部门对员工 是一对多,一对多是在一的那个类中(部门类)中添加一个员工集合对一 对的就是一个对象
对多 对的就是一个集合*/// 员工实体类// 对一就是对应的一个对象
// 对多就是对应的一个集合
public class Emp {private Integer empId;private String empName;private Integer age;private String gender;private Dept dept; // 加上一个部门的对象public Emp() {}public Emp(Integer empId, String empName, Integer age, String gender) {this.empId = empId;this.empName = empName;this.age = age;this.gender = gender;}public Integer getEmpId() {return empId;}public void setEmpId(Integer empId) {this.empId = empId;}public String getEmpName() {return empName;}public void setEmpName(String empName) {this.empName = empName;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public Dept getDept() {return dept;}public void setDept(Dept dept) {this.dept = dept;}@Overridepublic String toString() {return "Emp{" +"empId=" + empId +", empName='" + empName + '\'' +", age=" + age +", gender='" + gender + '\'' +", dept=" + dept +'}';}
}
DeptMapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mybatis.mapper.DeptMapper"><!-- 处理一对多的映射关系1. collection2. 分步查询
-->
<!--*************************** 一对多 collection ****************************************--><resultMap id="deptAndEmpById_resultMap" type="dept"><id column="dept_id" property="deptId"></id><result column="dept_name" property="deptName"></result><!-- collection : 处理一对多的映射关系(处理集合类型的属性)--><!-- ofType表示的是集合中的类型--><collection property="emps" ofType="Emp"><id column="emp_id" property="empId"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="gender" property="gender"></result></collection></resultMap><!-- Dept getDeptAndEmpById(@Param("deptId") Integer deptId);--><select id="getDeptAndEmpById" resultMap="deptAndEmpById_resultMap">select *from t_deptleft join t_emp on t_dept.dept_id = t_emp.dept_idwhere t_dept.dept_id=#{deptId}</select><!--*************************** 一对多 collection ****************************************--><!--*************************** 一对多 分步查询 ****************************************--><resultMap id="deptAndEmpResultMapByStep" type="Dept"><id column="dept_id" property="deptId"></id><result column="dept_name" property="deptName"></result><collection property="emps"select="com.atguigu.mybatis.mapper.DeptMapper.getDeptAndEmpByStepTwo"column="dept_id"></collection></resultMap><!-- Dept getDeptAndEmpByStepOne(@Param("deptId") int deptId);// 先查出指定id的部门信息,部门信息中有对应员工的dept_id --><select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpResultMapByStep">select * from t_dept where dept_id = #{deptId}</select><!-- List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") int deptId);// 再根据dept_id查出相对应的员工信息--><select id="getDeptAndEmpByStepTwo" resultType="Emp">select * from t_emp where dept_id = #{deptId}</select></mapper>
EmpMapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mybatis.mapper.EmpMapper"><!--处理多对一的映射关系有三种方法:第一种:级联方式处理第二种:association 处理多对一的映射关系(处理的是实体类类型的属性)第三种:分布查询--><!-- ************ 第一种:级联方式处理 *************** --><resultMap id="EmpAndDeptById_resultMap" type="Emp"><id column="emp_id" property="empId"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="gender" property="gender"></result><result column="dept_id" property="dept.deptId"></result><result column="dept_name" property="dept.deptName"></result></resultMap><!--Emp getEmpAndDeptById(@Param("empId") Integer empId);--><select id="getEmpAndDeptById" resultMap="EmpAndDeptById_resultMap">select *from t_empleft join t_dept on t_emp.dept_id = t_dept.dept_idwhere t_emp.emp_id=#{empId}</select><!-- *********************************************--><!-- *************** 第二种 association ******************************--><!-- 第二种 association--><resultMap id="getEmpAndDeptById_association_resultMap" type="Emp"><id column="emp_id" property="empId"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="gender" property="gender"></result><!--association: 处理多对一的映射关系(处理实体类类型的属性)property: 设置需要处理映射关系的属性的属性名javaType: 设置要处理的属性的类型, 就是把<association>标签下设置映射关系的字段,封装给某个类--><association property="dept" javaType="Dept"><id column="dept_id" property="deptId"></id><result column="dept_name" property="deptName"></result></association></resultMap><!-- Emp getEmpAndDeptById_association(@Param("empId") Integer empId);--><select id="getEmpAndDeptById_association" resultMap="getEmpAndDeptById_association_resultMap">select *from t_empleft join t_dept on t_emp.dept_id = t_dept.dept_idwhere t_emp.emp_id=#{empId}</select><!-- *********************************************--><!-- ****************** 第三种:分布查询 ***************************--><resultMap id="getEmpAndDeptByIdOne_resultMap" type="Emp"><id column="emp_id" property="empId"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="gender" property="gender"></result><!--property: 设置需要处理映射关系的属性的属性名select: 填写分步查询的sql的唯一标识,就是设置下一步要执行的sql语句column: 将上一个sql查询出的某个字段作为分步查询的下一个sql语句sql条件,相当于函数的参数,传给下一个sql语句fetchType: 在开启了延时加载的环境中,通过该属性设置当前的分步查询是否使用延迟加载有两个值:eager(立即加载) lazy(延迟加载)--><association property="dept"fetchType="eager"select="com.atguigu.mybatis.mapper.EmpMapper.getEmpAndDeptByIdTwo"column="dept_id"></association></resultMap><!-- Emp getEmpAndDeptByIdOne(@Param("empId") Integer empId);--><select id="getEmpAndDeptByIdOne" resultMap="getEmpAndDeptByIdOne_resultMap">select * from t_emp where emp_id = #{empId}</select><!-- Dept getEmpAndDeptByIdTwo(@Param("deptId") Integer deptId);--><select id="getEmpAndDeptByIdTwo" resultType="Dept">select * from t_dept where dept_id = #{deptId}</select><!-- *********************************************--></mapper>
ResultMapTest
import com.atguigu.mybatis.mapper.DeptMapper;
import com.atguigu.mybatis.mapper.EmpMapper;
import com.ruanjian.pojo.Dept;
import com.ruanjian.pojo.Emp;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;public class ResultMapTest {private SqlSession session;/*处理多对一的映射关系有三种方法:第一种:级联方式处理第二种:association 处理多对一的映射关系(处理的是实体类类型的属性)第三种:分步查询*/// *********************** 多对一 ****************************************@Test// 第三种:分步查询public void textGetEmpAndDeptByIdOne() {EmpMapper mapper = session.getMapper(EmpMapper.class);Emp emp = mapper.getEmpAndDeptByIdOne(1);System.out.println(emp);}@Test// 第二种:associationpublic void textGetEmpAndDeptById_association() {EmpMapper mapper = session.getMapper(EmpMapper.class);Emp emp = mapper.getEmpAndDeptById_association(2);System.out.println(emp);}@Test// 第一种:级联方式处理public void textGetEmpAndDeptById() {EmpMapper mapper = session.getMapper(EmpMapper.class);Emp emp = mapper.getEmpAndDeptById(2);System.out.println(emp);}// *********************** 一对多 ****************************************@Test// 分步查询public void textGetDeptAndEmpByStep() {DeptMapper mapper = session.getMapper(DeptMapper.class);Dept dept = mapper.getDeptAndEmpByStepOne(2);System.out.println(dept);}@Test// 一对多查询public void textGetDeptAndEmpById() {DeptMapper mapper = session.getMapper(DeptMapper.class);Dept dept = mapper.getDeptAndEmpById(1);System.out.println(dept);}// ***************************************************************// junit会在每一个@Test方法前执行@Before方法@Beforepublic void init() throws IOException {session = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession();}// junit会在每一个@Test方法后执行@After方法@Afterpublic void clear() {session.commit();session.close();}
}
db.properties
mysql.driver=com.mysql.cj.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
mysql.username=root
mysql.password=123456
log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"><appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"><param name="Encoding" value="UTF-8"/><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n"/></layout></appender><logger name="java.sql"><level value="debug"/></logger><logger name="org.apache.ibatis"><level value="info"/></logger><root><level value="debug"/><appender-ref ref="STDOUT"/></root>
</log4j:configuration>
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--环境配置--><!--引入外部db.properties--><properties resource="db.properties"/><settings><!-- <setting name="cacheEnabled" value="true" />--><!-- 开启延时加载--><setting name="lazyLoadingEnabled" value="true"/><!-- 开启时即为true时任何方法的调用都会加载相关类的全部属性false时是按需加载,true是全部加载--><setting name="aggressiveLazyLoading" value="false"/><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><package name="com.ruanjian.pojo"/></typeAliases><!--配置mybatis的连接环境(可以配置多个环境)--><environments default="development"><!--开发环境--><environment id="development"><!--使用JDBC事务管理--><transactionManager type="JDBC"/><!--数据库连接相关配置,db.properties文件中的内容--><!--使用连接池技术--><dataSource type="POOLED"><!--数据库驱动--><property name="driver" value="${mysql.driver}"/><!--连接字符串--><property name="url" value="${mysql.url}"/><!--数据库用户名--><property name="username" value="${mysql.username}"/><!--数据库密码--><property name="password" value="${mysql.password}"/></dataSource></environment></environments><!--mapping文件路径配置--><mappers><!-- <mapper resource="mapper/DeptMapper.xml"/>--><package name="com.atguigu.mybatis.mapper"/></mappers>
</configuration>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.itheima</groupId><artifactId>MyBaits_2</artifactId><version>1.0-SNAPSHOT</version><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>8</source><target>8</target></configuration></plugin></plugins></build><properties><maven.compiler.sourece>11</maven.compiler.sourece><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version><scope>runtime</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>text</scope></dependency><!-- log4j日志 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency></dependencies>
</project>
注意
新建包时用点
例如:com.atguigu.mybatis.mapper
resources目录下建立多层目录的时候时是用分割线
例如:com/atguigu/mybatis/mapper
mybatis-config.xml文件中
<package name="com.atguigu.mybatis.mapper"/>
<package>的使用条件:
接口文件要和xml文件同名,并且在同一个目录下
使用注解写的接口,只能有class的方式注册,例:
<mapper class="com.atguigu.mybatis.mapper.DeptMapper"></mapper>