文章目录
1. Mybatis 关联查询
1.1 创建新项目
1.1.1 选择项目
1.1.2 编辑POM.xml文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--引入插件lombok 自动的set/get/构造方法插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--mybatis依赖包-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!--jdbc依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
1.1.3 复制配置文件
1.2 创建表
1.2.1 创建员工表
emp_id int 主键自增
emp_name varchar(40)
dept_id int
- 表结构
- 表数据
1.2.2 创建部门表
dept部门表
dept_id int 主键自增
dept_name varchar(40)
1.表结构
2. 表数据
1.2.3 创建POJO对象
1.2.3.1 编辑Emp POJO
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Emp implements Serializable {
private Integer empId;
private String empName;
//关联关系 1: 一个员工对应一个部门
private Dept dept;
}
1.2.3.2 编辑Dept POJO
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {
private Integer deptId;
private String deptName;
//一个部门对应多个员工
private List<Emp> emps;
}
1.2.3.3 项目代码结构
1.3 常见表关系
秘诀: 从一头出发,看向另一头. 所在位置不同,得到的结果不同.
- 一对一 例子: 一个老公对应一个老婆 , 一个员工对应一个部门
- 一对多 例子: 一个部门对应多个员工.
- 多对多 例子: 一个学生对应多个老师, 一个老师对应多个学生.
- 一个角色对应多个权限, 一个权限对应多个角色
ps:- 多对多,其实就是双向的一对多
- 多对一 实质: 站在一头出发 所以 就是一对一
1.4 Mybatis 一对一封装
1.4.1 业务说明
表关系: 一个员工对应一个部门
Mybatis中映射规则: 结果集不允许出现重名字段.
Sql:
/*内连接的另外的一种表现形式.*/
SELECT e.emp_id,e.emp_name,
d.dept_id,d.dept_name
FROM emp e,dept d
WHERE e.dept_id = d.dept_id
1.4.2 测试类准备
package com.jt;
import com.jt.mapper.EmpMapper;
import com.jt.pojo.Emp;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
class SpringbootDemo3ApplicationTests {
/**
* SqlSessionFactory
*/
private SqlSessionFactory sqlSessionFactory;
@BeforeEach
public void init() throws IOException {
String resource = "mybatis/mybatis-config.xml";
InputStream inputStream =
Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
}
/**
* 进行一对一查询 一个员工对应一个部门
*/
@Test
void oneToOne() {
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> list = empMapper.findAll();
System.out.println(list);
sqlSession.close();
}
}
1.4.3 编辑Mapper接口/xml映射文件
- 编辑Mapper接口
public interface EmpMapper {
List<Emp> findAll();
}
- 编辑Mapper映射文件
<?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.jt.mapper.EmpMapper">
<!-- 一对一关联查询 -->
<select id="findAll" resultMap="empRM">
select e.emp_id,e.emp_name,
d.dept_id,d.dept_name
from emp e,dept d
where e.dept_id = d.dept_id
</select>
<!--3.完成一对一封装
固定用法:
1.association: 将结果集封装为单独的对象 dept
2.property 需要封装的属性名称
3.javaType 固定写法: 属性的类型
-->
<resultMap id="empRM" type="Emp">
<!--1.主键字段 -->
<id property="empId" column="emp_id"></id>
<!--2.映射其它属性字段-->
<result property="empName" column="emp_name"></result>
<association property="dept" javaType="Dept">
<!--3.完成dept对象的封装-->
<id property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
</association>
</resultMap>
</mapper>
1.4.4 一对一标签
1.5 一对多
1.5.1 业务场景
说明: 一个部门有多个员工.
Sql:
/*内连接的另外的一种表现形式.*/
SELECT d.dept_id,d.dept_name,e.emp_id,e.emp_name
FROM dept d,emp e
WHERE e.dept_id = d.dept_id
1.5.2 编辑测试方法
//一个部门下有多个员工 主表: dept
@Test
public void testOneToMore(){
SqlSession sqlSession = sqlSessionFactory.openSession();
DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
List<Dept> list = deptMapper.findAll();
System.out.println(list);
sqlSession.close();
}
1.5.3 编辑Mapper接口/映射文件
- mapper接口
public interface DeptMapper {
List<Dept> findAll();
}
- 编辑Mapper映射文件
<?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.jt.mapper.DeptMapper">
<select id="findAll" resultMap="deptRM">
select d.dept_id,d.dept_name,e.emp_id,e.emp_name
from dept d,emp e
where e.dept_id = d.dept_id
</select>
<!--Mybatis的映射,一般都是一级封装 -->
<resultMap id="deptRM" type="Dept">
<!--指定主键-->
<id column="dept_id" property="deptId"/>
<!--封装其它的属性字段-->
<result column="dept_name" property="deptName"/>
<!--封装集合 属于同一个部门下的员工,封装到一个集合中 -->
<collection property="emps" ofType="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
</collection>
</resultMap>
</mapper>
1.6 Mybatis的子查询
1.6.1 子查询原理
矛盾点:
- 如果想简化Sql,则映射文件肯定复杂.
- 如果想简化映射文件, 则Sql语句复杂.
案例说明: 需求 简化Sql, 那么映射文件复杂.
1.6.2 编辑测试案例
/**
* 利用Mybatis的子查询实现数据封装
*/
@Test
public void testOneToMore2(){
SqlSession sqlSession = sqlSessionFactory.openSession();
DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
List<Dept> list = deptMapper.selectChildren();
System.out.println(list);
sqlSession.close();
}
1.6.3 编辑Mapper接口/xml映射文件
- 编辑Mapper接口
- 编辑xml映射文件
<!--子查询:
1.标签: select 进行二次查询
2.关联字段信息: column="dept_id" 将字段的值作为参数 传递给子查询
-->
<resultMap id="cRM" type="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<!--数据集合封装-->
<collection property="emps" ofType="Emp" select="findEmp" column="dept_id"></collection>
</resultMap>
<select id="findEmp" resultMap="empRM">
select * from emp where dept_id = #{dept_id}
</select>
<resultMap id="empRM" type="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
</resultMap>
2 Mybatis关联查询小结
- 常见对应方式 1-1 1-多 多对多
- 对一封装 关键标签
- 对多封装 关键标签
- 什么时候使用resultMap
4.1 字段名称与属性名称不一致.
4.2 做关联查询 实现数据封装时使用. - 子查询用法:
5.1 select 开始二次查询
5.2 column 将字段的值作为参数传递给子查询 子查询通过#{字段名称}动态接收.