1、引入依赖
- <dependencies>
-
- <dependency>
- <groupId>org.mybatisgroupId>
- <artifactId>mybatisartifactId>
- <version>3.5.7version>
- dependency>
-
-
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.12version>
- <scope>testscope>
- dependency>
-
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>8.0.27version>
- dependency>
-
-
- <dependency>
- <groupId>log4jgroupId>
- <artifactId>log4jartifactId>
- <version>1.2.17version>
- dependency>
- dependencies>
2、创建数据表
- CREATE TABLE t_dept(
- dept_id INT PRIMARY KEY AUTO_INCREMENT,
- dept_name VARCHAR(20)
- );
-
- CREATE TABLE t_emp(
- emp_id INT PRIMARY KEY AUTO_INCREMENT,
- emp_name VARCHAR(20),
- age INT,
- gender CHAR,
- dept_id INT
- );
-
- INSERT INTO t_dept(dept_name) VALUES ('A'),('B'),('C');
-
- INSERT INTO t_emp(emp_name,age,gender,dept_id) VALUES
- ('张三',20,'女',1),
- ('李四',22,'女',2),
- ('王五',21,'男',3),
- ('赵六',23,'男',1),
- ('田七',21,'女',3);
3、创建与数据表相对应 java 实体类
- public class Emp {
- private Integer empId;
- private String empName;
- private Integer age;
- private String gender;
- private Integer deptId;
-
- public Emp() {
- }
-
- public Emp(Integer empId, String empName, Integer age, String gender, Integer deptId) {
- this.empId = empId;
- this.empName = empName;
- this.age = age;
- this.gender = gender;
- this.deptId = deptId;
- }
-
- 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 Integer getDeptId() {
- return deptId;
- }
-
- public void setDeptId(Integer deptId) {
- this.deptId = deptId;
- }
-
- @Override
- public String toString() {
- return "Emp{" +
- "empId=" + empId +
- ", empName='" + empName + '\'' +
- ", age=" + age +
- ", gender='" + gender + '\'' +
- ", deptId=" + deptId +
- '}';
- }
- }
- public class Dept {
- private Integer deptId;
- private String deptName;
-
- public Dept(Integer deptId, String deptName) {
- this.deptId = deptId;
- this.deptName = deptName;
- }
-
- public Dept() {
- }
-
- 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;
- }
-
- @Override
- public String toString() {
- return "Dept{" +
- "deptId=" + deptId +
- ", deptName='" + deptName + '\'' +
- '}';
- }
- }
4、jdbc.properties 文件
- jdbc.driver=com.mysql.cj.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
- jdbc.username=root
- jdbc.password=root
5、MyBaits 核心配置文件
- configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
-
-
-
- <properties resource="jdbc.properties"/>
-
- <typeAliases>
- <package name="com.chenyixin.ssm.pojo"/>
- typeAliases>
-
-
- <environments default="development">
- <environment id="development">
- <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.chenyixin.ssm.mapper"/>
- mappers>
- configuration>
6、工具类:
- package com.chenyin.ssm.utils;
-
- 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 java.io.InputStream;
-
- public class SqlSessionUtil {
-
- public static SqlSession getSqlSession() {
- try {
- // 获取核心的配置文件
- InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
- // 创建 SqlSessionFactoryBuilder 对象
- SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
-
- // 通过核心配置文件多对应的字节输入流创建工厂类 SqlSessionFactory ,生产 SqlSession 对象
- SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
-
- // 创建 SqlSession 对象(自动操作事务)
- return sqlSessionFactory.openSession(true);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- }
- }
7、log4j.xml配置文件
- 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>
字段名和属性名不一致的情况,如何处理映射关系:
1、为查询的字段设置别名,和属性名一致
2、当字段符合 MySql 的要求使用,而属性符合 java 的要求使用驼峰,此时可以在 MyBatis 的核心文件中使用 setting 标签设置一个全局变量配置,可以自动将下划线映射为驼峰
如:emp_id -> empId
3、使用 resultMap 自定义映射处理
resultMap:设置自定义的映射关系
id:唯一表示
type:处理映射关系的实体类的类型
常用标签
id: 处理主键和实体类中属性的映射关系
result:处理普通字段和实体类中属性的映射关系
column:设置映射关系中的字段名,必须是sql 查询出的某个字段
property:设置映射关系中的属性的属性名,必须是处理的实体类类型中的属性名
代码示例:
EmpMapper 接口:
- public interface EmpMapper {
- /**
- * 根据 empId 获取 emp 信息
- * @param empId
- * @return
- */
- Emp getEmpById(@Param("empId") Integer empId);
- }
EmpMapper.xml 配置文件:
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
- <mapper namespace="com.chenyixin.ssm.mapper.EmpMapper">
-
-
- <select id="getEmpById" resultType="emp">
-
- select * from t_emp where emp_id = #{empId}
- select>
- mapper>
配置核心文件:
-
- <settings>
- <setting name="mapUnderscoreToCamelCase" value="true"/>
- settings>
测试类:
- public class EmpMapperTest {
- SqlSession sqlSession = SqlSessionUtil.getSqlSession();
- EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
- DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
-
- @Test
- public void getEmpById() {
- Emp emp = empMapper.getEmpById(2);
- System.out.println(emp);
- // Emp{empId=2, empName='李四', age=22, gender='女', deptId=2}
- }
- }
EmpMapper 接口:
Emp getEmpById2(@Param("empId") Integer empId);
EmpMapper.xml 配置文件:
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
- <mapper namespace="com.chenyixin.ssm.mapper.EmpMapper">
- <resultMap id="empMap" type="Emp">
- <id column="emp_id" property="empId"/>
- <result column="emp_name" property="empName"/>
- <result column="age" property="age"/>
- <result column="gender" property="gender"/>
- <result column="dept_id" property="deptId"/>
- resultMap>
-
-
- <select id="getEmpById" resultType="emp">
- select * from t_emp where emp_id = #{empId}
- select>
-
- <select id="getEmpById2" resultMap="empMap">
- select * from t_emp where emp_id = #{empId}
- select>
- mapper>
测试:
- @Test
- public void getEmpById() {
- Emp emp = empMapper.getEmpById2(2);
- System.out.println(emp);
- // Emp{empId=2, empName='李四', age=22, gender='女', deptId=2}
- }
处理多对一的映射关系:
1、级联方式处理映射关系
2、使用association处理映射关系
3、分布查询方式处理映射关系
修改 emp 实体类:
- package com.chenyixin.ssm.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;
- }
-
- @Override
- public String toString() {
- return "Emp{" +
- "empId=" + empId +
- ", empName='" + empName + '\'' +
- ", age=" + age +
- ", gender='" + gender + '\'' +
- ", dept=" + dept +
- '}';
- }
- }
EmpMapper 接口:
- /**
- * 根据 empId 获取 emp 的所有信息(包括该员工的部门信息)
- * @param empId
- * @return
- */
- Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);
EmpMapper.xml 配置文件:
- <resultMap id="getEmpAndDeptMap" type="Emp">
- <id column="emp_id" property="empId"/>
- <result column="emp_name" property="empName"/>
- <result column="age" property="age"/>
- <result column="gender" property="gender"/>
- <result column="dept_id" property="dept.deptId"/>
- <result column="dept_name" property="dept.deptName"/>
- resultMap>
-
-
-
- <select id="getEmpAndDeptByEmpId" resultMap="getEmpAndDeptMap">
- select *
- from t_emp e
- left join t_dept d
- on e.dept_id = d.dept_id
- where emp_id = #{empId}
- select>
测试:
- @Test
- public void getEmpAndDeptByEmpId() {
- Emp emp = empMapper.getEmpAndDeptByEmpId(1);
- System.out.println(emp);
- // Emp{empId=1, empName='张三', age=20, gender='女', dept=Dept{deptId=1, deptName='A'}}
- }
association:处理多对一的映射关系(处理实体类类型的属性)
property:设置需要处理映射关系的属性的属性名
javaType:设置要处理的属性的类型
注意:一对一的映射关系可以用多对一的方式去处理
EmpMapper 接口:
Emp getEmpAndDeptByEmpId2(@Param("empId") Integer empId);
EmpMapper.xml 配置文件:
- <resultMap id="getEmpAndDeptMap2" type="Emp">
- <id column="emp_id" property="empId"/>
- <result column="emp_name" property="empName"/>
- <result column="age" property="age"/>
- <result column="gender" property="gender"/>
- <association property="dept" javaType="Dept">
- <id column="dept_id" property="deptId"/>
- <result column="dept_name" property="deptName"/>
- association>
- resultMap>
-
-
- <select id="getEmpAndDeptByEmpId2" resultMap="getEmpAndDeptMap2">
- select *
- from t_emp e
- left join t_dept d
- on e.dept_id = d.dept_id
- where emp_id = #{empId}
- select>
测试:
- @Test
- public void getEmpAndDeptByEmpId2() {
- Emp emp = empMapper.getEmpAndDeptByEmpId2(3);
- System.out.println(emp);
- // Emp{empId=3, empName='王五', age=21, gender='男', dept=Dept{deptId=3, deptName='C'}}
- }
association:处理多对一的映射关系(处理实体类类型的属性)
property:设置需要处理映射关系的属性的属性名
javaType:设置要处理的属性的类型
select : 设置分布查询的 sql 的唯一标识(namespace.id)
column:将查询出的某个字段作为分布查询的 sql 条件
EmpMapper 接口:
- /**
- * 分布查询:根据员工 id 查询对应员工信息 及其 该员工所对应的部门信息 (第二步)
- * @param deptId
- * @return
- */
- Dept getEmpAndDeptByStopTwo(@Param("deptId") Integer deptId);
DeptMapper 接口:
- /**
- * 分布查询:根据员工 id 查询对应员工信息 及其 该员工所对应的部门信息 (第一步)
- * @param empId
- * @return
- */
- Emp getEmpAndDeptByStopOne(@Param("empId") Integer empId);
DeptMapper.xml 配置文件:
- <mapper namespace="com.chenyixin.ssm.mapper.DeptMapper">
-
- <select id="getEmpAndDeptByStopTwo" resultType="dept">
- select * from t_dept where dept_id = #{deptId}
- select>
-
- mapper>
EmpMapper.xml 配置文件:
- <resultMap id="getEmpAndDeptStopMap" type="Emp">
- <id column="emp_id" property="empId"/>
- <result column="emp_name" property="empName"/>
- <result column="age" property="age"/>
- <result column="gender" property="gender"/>
- <association property="dept" select="com.chenyixin.ssm.mapper.DeptMapper.getEmpAndDeptByStopTwo" column="dept_id"/>
- resultMap>
-
-
- <select id="getEmpAndDeptByStopOne" resultMap="getEmpAndDeptStopMap">
- select * from t_emp where emp_id = #{empId}
- select>
测试:(记得开启全局配置)
- @Test
- public void getEmpAndDeptByStopOne() {
- Emp emp = empMapper.getEmpAndDeptByStopOne(4);
- System.out.println(emp);
- }
结果:(查询了两次)
概念:对于实体类关联的属性到需要使用时才查询。也叫懒加载。
在全局变量中设置延迟加载:
- <settings>
-
- <setting name="mapUnderscoreToCamelCase" value="true"/>
-
-
-
- <setting name="lazyLoadingEnabled" value="true"/>
-
-
- <setting name="aggressiveLazyLoading" value="false"/>
- settings>
测试1:(以在全局设置中开启了延迟加载)
- @Test
- public void getEmpAndDeptByStopOne() {
- Emp emp = empMapper.getEmpAndDeptByStopOne(4);
- System.out.println(emp.getEmpName());
- }
结果:
因为全局变量会对所有的分布查询开启延迟加载,但也可以在 Mapper配置文件中的resultMap 设置延迟加载。
association:
fetchType:在开启了延迟加载的环境中,通过该属性设置当前分布查询是否使用延迟加载
fetchType=“eager(立即加载) | lazy(延迟加载)”
- <resultMap id="getEmpAndDeptStopMap" type="Emp">
- <id column="emp_id" property="empId"/>
- <result column="emp_name" property="empName"/>
- <result column="age" property="age"/>
- <result column="gender" property="gender"/>
- <association property="dept" select="com.chenyixin.ssm.mapper.DeptMapper.getEmpAndDeptByStopTwo"
- column="dept_id" fetchType="eager"/>
- resultMap>
测试2:(测试代码与测试1相同)(以在全局设置中开启了延迟加载,但也在Mapper配置文件中的resultMap 设置了延迟加载)
结果:
处理一对多的映射关系
1、collection
2、分布查询
准备:
修改 dept 实体类:
-
- public class Dept {
- private Integer deptId;
- private String deptName;
- private List
emps; -
- public Dept(Integer deptId, String deptName) {
- this.deptId = deptId;
- this.deptName = deptName;
- }
-
- public Dept() {
- }
-
- 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;
- }
-
- @Override
- public String toString() {
- return "Dept{" +
- "deptId=" + deptId +
- ", deptName='" + deptName + '\'' +
- ", emps=" + emps +
- '}';
- }
- }
collection (其子标签与 association 子标签用法相同)
collection:处理一对多的映射关系(处理集合类型的属性)
ofType:设置集合类型的属性中存储的数据的类型
DeptMapper 接口:
- /**
- * 根据部门 id 查询部门以及部门中的员工信息
- * @param deptId
- * @return
- */
- Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);
DeptMapper.xml 配置文件:
- <resultMap id="getDeptAndEmpMap" type="Dept">
- <id column="dept_id" property="deptId"/>
- <id column="dept_name" property="deptName"/>
- <collection property="emps" ofType="Emp">
- <id column="emp_id" property="empId"/>
- <id column="emp_name" property="empName"/>
- <id column="age" property="age"/>
- <id column="gender" property="gender"/>
- collection>
- resultMap>
-
-
- <select id="getDeptAndEmpByDeptId" resultMap="getDeptAndEmpMap">
- select *
- from t_dept d
- left join t_emp e on d.dept_id = e.dept_id
- where d.dept_id = #{deptId}
- select>
测试:
- public class DeptMapperTest {
- SqlSession sqlSession = SqlSessionUtil.getSqlSession();
- DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
-
- @Test
- public void getDeptAndEmpByDeptId() {
- Dept dept = deptMapper.getDeptAndEmpByDeptId(1);
- System.out.println(dept);
- // Dept{deptId=1, deptName='A',
- // emps=[Emp{empId=1, empName='张三', age=20, gender='女', dept=null},
- // Emp{empId=4, empName='赵六', age=23, gender='男', dept=null}]}
- }
- }
DeptMapper 接口:
- /**
- * 通过分布查询 查询部门以及部门中的员工信息的第一步
- * @param deptId
- * @return
- */
- Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);
EmpMapper 接口:
- /**
- * 通过分布查询 查询部门以及部门中的员工信息的第二步
- * @param deptId
- * @return
- */
- Emp getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);
EmpMapper.xml 配置文件:
-
- <select id="getDeptAndEmpByStepTwo" resultType="emp">
- select * from t_emp where dept_id = #{deptId};
- select>
DeptMapper.xml 配置文件:
- <resultMap id="getDeptAndEmpStepMap" type="Dept">
- <id column="dept_id" property="deptId"/>
- <result column="dept_name" property="deptName"/>
- <collection property="emps"
- select="com.chenyixin.ssm.mapper.EmpMapper.getDeptAndEmpByStepTwo"
- column="dept_id"/>
- resultMap>
-
- <select id="getDeptAndEmpByStepOne" resultMap="getDeptAndEmpStepMap">
- select * from t_dept where dept_id = #{deptId};
- select>
测试:
- @Test
- public void getDeptAndEmpByStepOne() {
- Dept dept = deptMapper.getDeptAndEmpByStepOne(3);
- System.out.println(dept);
- }
结果:
字段名和属性名不一致的情况,如何处理映射关系:
1、为查询的字段设置别名,和属性名一致
2、当字段符合 MySql 的要求使用,而属性符合 java 的要求使用驼峰,
此时可以在 MyBatis 的核心文件中使用 setting 标签设置一个全局变量配置,
可以自动将下划线映射为驼峰
如:emp_id -> empId
3、使用 resultMap 自定义映射处理
resultMap:设置自定义的映射关系
id:唯一表示
type:处理映射关系的实体类的类型常用标签
id: 处理主键和实体类中属性的映射关系
result:处理普通字段和实体类中属性的映射关系
column:设置映射关系中的字段名,必须是sql 查询出的某个字段
property:设置映射关系中的属性的属性名,必须是处理的实体类类型中的属性名
映射关系处理:
使用 resultMap 自定义映射处理
处理多对一的映射关系:
1、级联方式处理映射关系
2、使用 association 处理映射关系
3、分布查询方式处理映射关系
处理一对多的映射关系
1、collection
2、分布查询
resultMap:设置自定义的映射关系
id:唯一表示
type:处理映射关系的实体类的类型
常用标签
id: 处理主键和实体类中属性的映射关系
result:处理普通字段和实体类中属性的映射关系
column:设置映射关系中的字段名,必须是sql 查询出的某个字段
property:设置映射关系中的属性的属性名,必须是处理的实体类类型中的属性名
association:处理多对一的映射关系(处理实体类类型的属性)
property:设置需要处理映射关系的属性的属性名
javaType:设置要处理的属性的类型
select : 设置分布查询的 sql 的唯一标识(namespace.id)
column:将查询出的某个字段作为分布查询的 sql 条件
fetchType:在开启了延迟加载的环境中,通过该属性设置当前分布查询是否使用延迟加载
fetchType=“eager(立即加载) | lazy(延迟加载)”注意:一对一的映射关系可以用多对一的方式去处理
collection:处理一对多的映射关系(处理集合类型的属性)
property:设置需要处理映射关系的属性的属性名
ofType:设置集合类型的属性中存储的数据的类型
select : 设置分布查询的 sql 的唯一标识(namespace.id)
column:将查询出的某个字段作为分布查询的 sql 条件
fetchType:在开启了延迟加载的环境中,通过该属性设置当前分布查询是否使用延迟加载
fetchType=“eager(立即加载) | lazy(延迟加载)”注意:多对多的映射关系可以用一对多的方式去处理
全局变量的设置:
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> settings>