MyBatis 笔记¶
实现¶
- JDBC:Dao层(Java代码+SQL语句)
- MyBatis:Mapper接口(Java代码)+MapperXML文件(SQL语句)
Mapper接口
Java
// Mapper接口文件
package com.atguigu.mapper;
import com.atguigu.pojo.Employee;
public interface EmployeeMapper {
/**
* 根据员工id查询员工数据方法
* @param empId 员工id
* @return 员工实体对象
*/
Employee selectEmployee(Integer empId);
}
MapperXML配置
XML
<!-- MapperXML文件 -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.atguigu.mapper.EmployeeMapper">
<!-- 查询使用 select标签
id = 方法名
resultType = 返回值类型
标签内编写SQL语句
-->
<select id="selectEmployee" resultType="com.atguigu.pojo.Employee">
<!-- #{empId}代表动态传入的参数,并且进行赋值!后面详细讲解 -->
select emp_id empId,emp_name empName, emp_salary empSalary from
t_emp where emp_id = #{empId}
</select>
</mapper>
- 方法名和SQL的id一致
- 方法返回值和resultType一致
- 方法的参数和SQL的参数一致
- 接口的全类名和映射配置文件的名称空间一致
具体调用
Java
//1.读取外部配置文件
InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);
//3.创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.获取mapper代理对象
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
//5.数据库方法调用
int rows = empMapper.deleteEmpById(1);
System.out.println("rows = " + rows);
//6.提交和回滚
sqlSession.commit();
sqlSession.close();
SqlSessionFactory 和 Mapper 实例需交给 IoC 进行管理,MyBatis 提供了封装 SqlSessionFactory 和 Mapper 实例化的逻辑的FactoryBean组件:SqlSessionFactoryBean
Java
// Mapper 配置类
/**
* 配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可
* @param dataSource 需要注入连接池对象
* @return 工厂Bean
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
//实例化SqlSessionFactory工厂
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//设置连接池
sqlSessionFactoryBean.setDataSource(dataSource);
//设置配置文件
//包裹外部配置文件地址对象
Resource resource = new ClassPathResource("mybatis-config.xml");
sqlSessionFactoryBean.setConfigLocation(resource);
return sqlSessionFactoryBean;
}
/**
* 配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包
* @return
*/
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//设置mapper接口和xml文件所在的共同包
mapperScannerConfigurer.setBasePackage("com.atguigu.mapper");
return mapperScannerConfigurer;
}
基本使用¶
SQL传参¶
#{}
:占位符${}
:底层是字符串拼接
数据输入¶
- 单参数:SQL语句中的#{}可随意命名,建议和Mapper接口方法的参数名一致
- POJO实体类:根据#{}中传入的数据,加工成getXxx()方法,通过反射在实体类对象中调用该方法,从而获取数据
- 多参数:在Mapper接口方法的参数旁 定义@Param("xxx")
- Map参数:#{}中写Map中的key
数据输出¶
- 增删改操作返回受影响的行数,使用int / long类型接收
- 查询操作返回查询结果
返回类型
resultType = "全限定符 | 别名 | 如果是返回集合类型,写范型类型即可"
- 若返回Map,resultType = “map”
- 若返回List,resultType 为泛型类型
- 若返回实体类,resultType 为实体类的全类名
- 返回自增主键,useGeneratedKeys="true" keyProperty="empId" ,其中keyProperty为主键在实体类中的属性名
多表映射¶
关联关系 | 配置项关键词 | 所在配置文件和具体位置 |
---|---|---|
对一 | association标签/javaType属性/property属性 | Mapper配置文件中的resultMap标签内 |
对多 | collection标签/ofType属性/property属性 | Mapper配置文件中的resultMap标签内 |
动态语句¶
where / if 标签
SQL
<where>
<if test="empName != null">
or emp_name=#{empName}
</if>
<if test="empSalary > 2000">
or emp_salary>#{empSalary}
</if>
</where>
set 标签
SQL
<!-- 使用set标签动态管理set子句,并且动态去掉两端多余的逗号 -->
<set>
<if test="empName != null">
emp_name=#{empName},
</if>
<if test="empSalary < 3000">
emp_salary=#{empSalary},
</if>
</set>
choose / when / otherwise 标签
- 遇到的第一个满足条件的分支会被采纳
- 被采纳分支后面的分支都将不被考虑
- 如果所有的when分支都不满足,那么就执行otherwise分支
SQL
<choose>
<when test="empName != null">emp_name=#{empName}</when>
<when test="empSalary < 3000">emp_salary < 3000</when>
<otherwise>1=1</otherwise>
</choose>
foreach 标签
- collection属性:要遍历的集合
- item属性:遍历集合的过程中能得到每一个具体对象,在item属性中设置一个名字,将来通过这个名字引用遍历出来的对象
- separator属性:指定当foreach标签的标签体重复拼接字符串时,各个标签体字符串之间的分隔符
- open属性:指定整个循环把字符串拼好后,字符串整体的前面要添加的字符串
- close属性:指定整个循环把字符串拼好后,字符串整体的后面要添加的字符串
- index属性:这里起一个名字,便于后面引用。遍历List集合,这里能够得到List集合的索引值;遍历Map集合,这里能够得到Map集合的key
SQL
<foreach collection="empList" item="emp" separator="," open="values" index="myIndex">
<!-- 在foreach标签内部如果需要引用遍历得到的具体的一个对象,需要使用item属性声明的名称 -->
(#{emp.empName},#{myIndex},#{emp.empSalary},#{emp.empGender})
</foreach>