目录
一、MyBatis简介
1.1 MyBatis介绍
为什么需要Mybatis?
二、MyBatis框架部署
2.1 创建Maven项目
2.2 在项目中添加MyBatis依赖
2.3 创建MyBatis配置文件
三、MyBatis框架使用
3.1 创建数据表
3.2 创建实体类
3.3 创建DAO接口,定义操作方法
3.4 创建DAO接口的映射文件
3.5 将映射文件添加到主配置文件
四、单元测试
4.1 添加单元测依赖
4.2 创建单元测试类
4.3 测试代码
五、MyBatis的CRUD操作
5.1 添加操作
5.2 删除操作
5.3 修改操作
5.4 查询操作-查询所有
5.5 查询操作-查询一条记录
5.6 查询操作-多参数查询
5.7 查询操作-查询总记录数
5.8 添加操作回填生成的主键
六、MyBatis工具类封装
七、事务管理
7.1 手动提交事务
7.2 自动提交事务
八、MyBatis主配置文件
8.1 properties标签
8.2 settings标签
8.3 typeAliases标签
8.4 plugins标签
8.5 environments标签
8.6 mappers标签
九、映射文件
9.1 MyBatis Mapper初始化
9.2 mapper根标签
9.3 insert标签
9.4 delete标签
9.5 update标签
9.6 select标签
9.7 resultMap标签
9.8 cache标签
9.9 sql和include
十、分页插件
10.1 添加分页插件的依赖
10.2 配置插件
10.3 分页实例
MyBatis是一个
半自动
的ORM
框架ORM(Object Relational Mapping)对象关系映射,将Java中的一个对象与数据表中一行记录一一对应。
ORM框架提供了实体类与数据表的映射关系,通过映射文件的配置,实现对象的持久化。
中文文档:mybatis – MyBatis 3 | 简介
Github:GitHub - mybatis/mybatis-3: MyBatis SQL mapper framework for Java
MyBatis的前身是iBatis,iBatis是Apache软件基金会提供的一个开源项目
2010年iBatis迁移到Google code,正式更名为MyBatis
2013年迁移到Github托管
MyBatis特点:
支持自定义SQL、存储过程
对原有的JDBC进行了封装,几乎消除了所有JDBC代码,让开发者只需关注SQL本身
支持XML和注解配置方式自定完成ORM操作,实现结果映射
持久化-->数据持久化
持久化就是将程序的数据在持久状态和瞬时状态转化的过程
内存:断电即失
数据库(Jdbc),io文件持久化
生活方面例子:冷藏,罐头。
为什么需要持久化?
不想丢掉一些对象
内存太贵
持久层
Dao层,Service层,Controller层…
完成持久化工作的代码块
层界限十分明显
帮助程序猿将数据存入到数据库中
方便
传统的JDBC代码太复杂,简化–>框架–>自动化
最重要的一点:使用的人多! Spring-SpringMVC-SpringBoot
框架部署,就是将框架引入到我们的项目中
思路:搭建环境–>导入Mybatis–>编写代码–>测试
Java工程
Web工程
在pom.xml中添加依赖
mybatis
mysql driver
mysql
mysql-connector-java
5.1.47
org.mybatis
mybatis
3.4.6
在resources中创建名为mybatis-config.xml
的文件
在mybatis-config.xml
文件配置数据库连接信息
案例:学生信息的数据库操作
tb_students |
---|
Student.java (导入lombok依赖) |
---|
StudentDAO.java |
---|
在resources
目录下,新建名为mappers
文件夹
在mappers
中新建名为StudentMapper.xml
的映射文件(根据模板创建)
在映射文件中对DAO中定义的方法进行实现:
insert into tb_students(stu_num,stu_name,stu_gender,stu_age)
values(#{stuNum},#{stuName},#{stuGender},#{stuAge})
delete from tb_students where stu_num=#{stuNum}
mybatis-config.xml |
---|
junit
junit
4.12
在被测试类名后alt+insert --- 选择Test |
---|
package com.qfedu.dao;
import com.qfedu.pojo.Student;
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.IOException;
import java.io.InputStream;
import static org.junit.Assert.*;
public class StudentDAOTest {
@org.junit.Test
public void insertStudent() {
try {
//加载mybatis配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//会话工厂
SqlSessionFactory factory = builder.build(is);
//会话(连接)
SqlSession sqlSession = factory.openSession();
//通过会话获取DAO对象
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
//测试StudentDAO中的方法
int i = studentDAO.insertStudent(new Student(0, "10001", "张三", "男", 21));
//需要手动提交
sqlSession.commit();
System.out.println(i);
} catch (IOException e) {
e.printStackTrace();
}
}
@org.junit.Test
public void deleteStudent() {
}
}
可能遇到的问题:
配置文件没有注册;
绑定接口错误;
方法名不对;
返回类型不对;
Maven导出资源问题。
src/main/resources
**/*.properties
**/*.xml
true
src/main/java
**/*.properties
**/*.xml
true
说明:标准的Maven项目都会有一个resources目录来存放我们所有的资源配置文件,但是我们往往在项目中不仅仅会把所有的资源配置文件都放在resources中,同时我们也有可能放在项目中的其他位置,那么默认的maven项目构建编译时就不会把我们其他目录下的资源配置文件导出到target目录中,就会导致我们的资源配置文件读取失败,从而导致我们的项目报错出现异常,比如说尤其我们在使用MyBatis框架时,往往Mapper.xml配置文件都会放在dao包中和dao接口类放在一起的,那么执行程序的时候,其中的xml配置文件就一定会读取失败,不会生成到maven的target目录中,所以我们要在项目的pom.xml文件中进行设置,并且我建议大家,每新建一个maven项目,就把该设置导入pom.xml文件中,以防不测!!!
案例:学生信息的增删查改
略
根据学号删除一条学生信息
在StudentDAO中定义删除方法
StudentDAO |
---|
在StudentMapper.xml中对接口方法进行“实现”
StudentMapper.xml |
---|
测试:在StudentDAO的测试类中添加测试方法
StudentDAOTest |
---|
根据学生学号,修改其他字段信息
在StudentDAO接口中定义修改方法
StudentDAO |
---|
在StudentMapper.xml中“实现”接口中定义的修改方法
StudentMapper.xml |
---|
单元测试
StudentDAOTest |
---|
在StudentDAO接口定义操作方法
StudentDAO |
---|
在StudentMapper.xml中“实现”DAO中定义的方法
StudentMapper.xml |
---|
单元测试
StudentDAOTest |
---|
根据学号查询一个学生信息
在StudentDAO接口中定义方法
StudentDAO |
---|
在StudentDAOMapper.xml中配置StudentDAO接口的方法实现——SQL
StudentDAOMapper.xml |
---|
单元测试
StudentDAOTest |
---|
分页查询(参数 start , pageSize)
在StudentDAO中定义操作方法,如果方法有多个参数,使用@Param
注解声明参数的别名
StudentDAO |
---|
在StudentMapper.xml配置sql时,使用#{别名}
获取到指定的参数
StudentMapper.xml |
---|
注意
如果DAO操作方法没有通过@Param指定参数别名,在SQL中也可以通过arg0,arg1...
或者param1,param2,...
获取参数
在StudentDAO接口中定义操作方法
StudentDAO |
---|
在StudentMapper.xml配置sql,通过resultType指定当前操作的返回类型为int
StduentMapper.xml的添加操作标签——insert
insert into tb_students(stu_num, stu_name, stu_gender, stu_age)
values (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
MyBatisUtil
public class MyBatisUtil {
private static SqlSessionFactory factory;
private static final ThreadLocal local = new ThreadLocal();
static{
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getFactory(){
return factory;
}
public static SqlSession getSqlSession(){
SqlSession sqlSession = local.get();
if(sqlSession == null ){
sqlSession = factory.openSession();
local.set(sqlSession);
}
return sqlSession;
}
public static T getMapper(Class c){
SqlSession sqlSession = getSqlSession();
return sqlSession.getMapper(c);
}
}
SqlSession 对象
getMapper(DAO.class) : 获取Mapper(DAO接口的实例)
事务管理
sqlSession.commit();
提交事务
sqlSession.rollback();
事务回滚
测试类中进行事务管理
@Test
public void insertStudent() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
//1.当我们获取sqlSession对象时,就默认开启了事务
try{
//通过会话获取DAO对象
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
//测试StudentDAO中的方法
Student student = new Student(0, "10005", "Lily", "女", 21);
int i = studentDAO.insertStudent(student);
//2.操作完成并成功之后,需要手动提交
sqlSession.commit();
}catch (Exception e){
//3.当操作出现异常,调用rollback进行回滚
sqlSession.rollback();
}
}
业务逻辑层手动事务管理
public class StudentServiceImpl implements StudentService {
public boolean addStudent(Student student) {
boolean b = false;
SqlSession sqlSession = MyBatisUtil.getSqlSession();
try{
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
int i = studentDAO.insertStudent(student);
b = i>0;
sqlSession.commit();
}catch (Exception e){
sqlSession.rollback();
}
return b;
}
}
通过SqlSessionFactory调用openSession方法获取SqlSession对象时,可以通过参数设置事务是否自动提交:
如果参数设置为true,表示自定提交事务: factory.openSession(true);
如果参数设置为false,或者不设置参数,表示手动提交:factory.openSession();/factory.openSession(false);
MyBatisUtil优化
public class MyBatisUtil {
private static SqlSessionFactory factory;
private static final ThreadLocal local = new ThreadLocal();
static{
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getFactory(){
return factory;
}
private static SqlSession getSqlSession(boolean isAutoCommit){
SqlSession sqlSession = local.get();
if(sqlSession == null ){
sqlSession = factory.openSession(isAutoCommit);
local.set(sqlSession);
}
return sqlSession;
}
//手动事务管理
public static SqlSession getSqlSession(){
return getSqlSession(false);
}
//自动事务提交
public static T getMapper(Class c){
SqlSession sqlSession = getSqlSession(true);
return sqlSession.getMapper(c);
}
}
测试操作
@Test
public void testDeleteStudent() {
StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class);
int i = studentDAO.deleteStudent("10001");
}
业务逻辑层自动事务管理
public class StudentServiceImpl implements StudentService {
private StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class);
public boolean addStudent(Student student) {
int i = studentDAO.insertStudent(student);
boolean b = i>0;
return b;
}
}
mybatis-config.xml 是MyBatis框架的主配置文件,只要用于配置MyBatis数据源及属性信息
用于设置键值对,或者加载属性文件
在resources目录下创建jdbc.properties
文件,配置键值对如下:
mysql_driver=com.mysql.jdbc.Driver
mysql_url=jdbc:mysql://localhost:3306/db_2010_fmwy?characterEncoding=utf-8
mysql_username=root
mysql_password=admin123
在mybatis-config.xml中通过properties
标签引用jdbc.properties
文件;引入之后,在配置environment时可以直接使用jdbc.properties的key获取对应的value
mybatis-config.xml |
---|
加载映射配置(映射文件、DAO注解)
XML文件解析:读取xml文件中的标签配置封装到Java对象中
mapper文件相当于DAO接口的‘实现类’,namespace属性要指定
实现
DAO接口的全限定名
声明添加操作(sql: insert ...)
常用属性
id属性,绑定对应DAO接口中的方法
parameterType属性,用以指定接口中对应方法的参数类型(可省略)
useGeneratedKeys属性, 设置添加操作是否需要回填生成的主键
keyProperty属性,指定回填的id设置到参数对象中的哪个属性
timeout属性,设置此操作的超时时间,如果不设置则一直等待
主键回填
insert into tb_students(stu_num, stu_name, stu_gender, stu_age)
values (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
select last_insert_id()
insert into tb_students(stu_num, stu_name, stu_gender, stu_age)
values (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
声明删除操作
声明修改操作
声明查询操作
id属性, 指定绑定方法的方法名
parameterType属性,设置参数类型
resultType属性,指定当前sql返回数据封装的对象类型(实体类)
resultMap属性,指定从数据表到实体类的字段和属性的对应关系
useCache属性,指定此查询操作是否需要缓存
timeout属性,设置超时时间
设置当前DAO进行数据库操作时的缓存属性设置
SQL片段
sid , stu_num , stu_name , stu_gender , stu_age
分页插件是一个独立于MyBatis框架之外的第三方插件;
PageHelper
com.github.pagehelper
pagehelper
5.1.10
在mybatis的主配置文件
mybatis-config.xml
中通过plugins
标签进行配置
对学生信息进行分页查询
@Test
public void testListStudentsByPage() {
StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class); //sqlSession
PageHelper.startPage(2,4);
List students = studentDAO.listStudents();
PageInfo pageInfo = new PageInfo(students);
//pageInfo中就包含了数据及分页信息
}
带条件分页
@Test
public void testListStudentsByPage() {
StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class); //sqlSession
PageHelper.startPage(2,4);
//List students = studentDAO.listStudents();
List list = studentDAO.listStudentsByGender("女");
PageInfo pageInfo = new PageInfo(list);
//pageInfo中就包含了数据及分页信息
}