MyBatis 是基于 Java 的数据持久层框架
持久化:数据从瞬时状态变为持久状态 持久层:完成持久化工作的代码块 DAO
简而言之:
MyBatis 将数据存入数据库中,从数据库中取数据
通过框架可以减少重复代码,提高开发效率
MyBatis 是一个半自动化的 ORM 框架 Object Relationship Mapping
文档: https://mybatis.org/mybatis-3/zh/index.html
1、依赖
org.mybatis
mybatis
3.5.4
2、配置数据库
mybatis-config.xml
3、SQL 工厂类
package com.pengshiyu.mybatis.util;
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;
public class MyBatisUtil {
public static SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}
public static SqlSession getSqlSession() throws IOException {
SqlSession session = getSqlSessionFactory().openSession();
return session;
}
}
4、创建实体类
package com.pengshiyu.mybatis.entity;
public class Student {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
5、编写 SQL 语句映射文件
StudentMapper.xml
select * from students where id = #{id}
6、测试
package com.pengshiyu.mybatis.test;
import com.pengshiyu.mybatis.entity.Student;
import com.pengshiyu.mybatis.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
public class Demo {
public static void main(String[] args) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
Student student = session.selectOne("com.pengshiyu.mybatis.entity.StudentMapper.selectStudent", 3);
System.out.println(student);
session.close();
// Student{id=3, name='李白', age=30}
}
}
curd 操作
StudentMapper.xml
select * from students where id = #{id}
select * from students
insert into students(name, age) values(#{name}, #{age})
update students set name = #{name}, age = #{age} where id = #{id}
delete from students where id = #{id}
package com.pengshiyu.mybatis.dao;
import com.pengshiyu.mybatis.entity.Student;
import com.pengshiyu.mybatis.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
import java.util.List;
public class StudentDao {
public Student select(int id) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
Student student = session.selectOne("com.pengshiyu.mybatis.entity.StudentMapper.selectStudent", id);
session.close();
return student;
}
public List selectAll() throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
List students = session.selectList("com.pengshiyu.mybatis.entity.StudentMapper.selectAllStudent");
session.close();
return students;
}
public int insert(Student student) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
int result = session.insert("com.pengshiyu.mybatis.entity.StudentMapper.insertStudent", student);
session.commit();
session.close();
return result;
}
public int update(Student student) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
int result = session.update("com.pengshiyu.mybatis.entity.StudentMapper.updateStudent", student);
session.commit();
session.close();
return result;
}
public int delete(int id) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
int result = session.delete("com.pengshiyu.mybatis.entity.StudentMapper.deleteStudent", id);
session.commit();
session.close();
return result;
}
}
package com.pengshiyu.mybatis.test;
import com.pengshiyu.mybatis.dao.StudentDao;
import com.pengshiyu.mybatis.entity.Student;
import java.io.IOException;
import java.util.List;
public class Demo {
public static void main(String[] args) throws IOException {
StudentDao studentDao = new StudentDao();
// 查询
Student student = studentDao.select(3);
System.out.println(student);
// Student{id=3, name='李白', age=30}
// 写入
Student student = new Student();
student.setName("Jack");
student.setAge(23);
System.out.println(studentDao.inset(student));
// 1
// 更新
Student student = studentDao.select(16);
student.setAge(33);
student.setName("Tom");
System.out.println(studentDao.update(student));
// 1
// 删除数据
System.out.println(studentDao.delete(12));
// 1
// 查询多条数据
List students = studentDao.selectAll();
for(Student student: students){
System.out.println(student);
}
}
}
配置文件解析
配置文件
每个数据库对应一个 SqlSessionFactory 实例
dataSource:
- UNPOOLED 每次请求时打开和关闭连接
- POOLED 使用连接池
- JNDI 能在如 EJB 或应用服务器这类容器中使用
mapper 文件
namespace 命名规则: 包名+类名/包名+mapper 文件名
- parameterType 参数类型
- resultType 返回结果类型
- useGeneratedKeys=“true” 使用自增主键
执行流程
- 读取核心配置文件
- sqlSessionFactory 类
- sqlSession
- 执行相关操作
1、可以将数据库配置单独放在一个文件里边
db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/data
username=root
password=123456
2、别名配置
使用别名
select * from students
属性名和列名不一致
MyBatis 会根据列名取赋值,会将列名转为小写
1、为列名指定别名
select id, name, age as old from students where id = #{id}
2、使用结果映射类型
select id, name, age from students where id = #{id}
分页的实现
1、sql 中实现 如果将数据看做下标从 0 开始,那么就是数据切片 [startIndex, pageSize)
select * from students limit #{offset}, #{limit}
public class StudentDao {
public List selectAll(int currentPage, int pageSize) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
Map map = new HashMap();
map.put("offset", (currentPage - 1) * pageSize);
map.put("limit", pageSize);
List students = session.selectList(
"com.pengshiyu.mybatis.entity.StudentMapper.selectAllStudent", map);
session.close();
return students;
}
}
public class Demo {
public static void main(String[] args) throws IOException {
StudentDao studentDao = new StudentDao();
// 查询第二页的数据,每页2条
List students = studentDao.selectAll(2 , 2);
for(Student student: students){
System.out.println(student);
}
}
}
2、使用 RowBounds
select * from students
import org.apache.ibatis.session.RowBounds;
public class StudentDao {
public List selectAll(int currentPage, int pageSize) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
RowBounds rowBounds = new RowBounds((currentPage - 1) * pageSize, pageSize);
List students = session.selectList(
"com.pengshiyu.mybatis.entity.StudentMapper.selectAllStudent",
null, rowBounds);
session.close();
return students;
}
}
通过打印的日志发现:
- sql 限制起始位置和返回数量,currentPage=2, pageSize=2 时返回 2 条数据
- RowBounds 不限制起始位置,currentPage=2, pageSize=2 时返回 4 条数据
面向接口编程
扩展性好,分层开发中,上层不用管具体实现,
大家都遵循共同的实现,开发变得容易,规范性更好
DAO 接口
package com.pengshiyu.mybatis.dao;
import com.pengshiyu.mybatis.entity.Student;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface IStudentDao {
@Select("select * from students")
public List getList();
}
修改配置文件
测试使用
package com.pengshiyu.mybatis.test;
import com.pengshiyu.mybatis.dao.IStudentDao;
import com.pengshiyu.mybatis.dao.StudentDao;
import com.pengshiyu.mybatis.entity.Student;
import com.pengshiyu.mybatis.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
import java.util.List;
public class Demo {
public static void main(String[] args) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
IStudentDao studentDao = session.getMapper(IStudentDao.class);
List students = studentDao.getList();
for(Student student : students){
System.out.println(student);
}
}
}
多对一的处理
多个学生 student 对一个老师 teacher
1、数据库表设计
create table teachers(
id int PRIMARY key auto_increment,
name varchar(10)
);
create table students(
id int PRIMARY key auto_increment,
name varchar(10),
teacher_id int
);
insert into teachers(name) values("王老师");
insert into teachers(name) values("李老师");
insert into teachers(name) values("赵老师");
insert into students(name, teacher_id) values("宋江", 1);
insert into students(name, teacher_id) values("李逵", 1);
insert into students(name, teacher_id) values("鲁智深", 2);
insert into students(name, teacher_id) values("林冲", 3);
insert into students(name, teacher_id) values("高俅", 3);
2、实体类
Teacher
package com.pengshiyu.mybatis.entity;
public class Teacher {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
Student
package com.pengshiyu.mybatis.entity;
public class Student {
private int id;
private String name;
private Teacher teacher;
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", teacher=" + teacher +
'}';
}
}
3、映射文件
多对一处理方式:
(1)按结果嵌套
查询一次
select s.id sid, s.name sname, t.id tid, t.name tname
from students as s
left join teachers as t
on s.teacher_id = t.id
- 按查询嵌套
会查询 n 次,n 是 Student 数量
select * from students
select * from teachers where id = #{id}
4、引入映射文件
mybatis-config.xml
5、Dao 编写
package com.pengshiyu.mybatis.dao;
import com.pengshiyu.mybatis.entity.Student;
import com.pengshiyu.mybatis.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
import java.util.List;
public class StudentDao {
public List selectAll() throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
List students = session.selectList(
"com.pengshiyu.mybatis.entity.StudentMapper.selectAllStudent");
session.close();
return students;
}
}
6、测试类
package com.pengshiyu.mybatis.test;
import com.pengshiyu.mybatis.dao.StudentDao;
import com.pengshiyu.mybatis.entity.Student;
import java.io.IOException;
import java.util.List;
public class Demo {
public static void main(String[] args) throws IOException {
StudentDao studentDao = new StudentDao();
List students = studentDao.selectAll();
for(Student student: students){
System.out.println(student);
}
}
}
查询结果
Student{id=1, name='宋江', teacher=Teacher{id=1, name='王老师'}}
Student{id=2, name='李逵', teacher=Teacher{id=1, name='王老师'}}
Student{id=3, name='鲁智深', teacher=Teacher{id=2, name='李老师'}}
Student{id=4, name='林冲', teacher=Teacher{id=3, name='赵老师'}}
Student{id=5, name='高俅', teacher=Teacher{id=3, name='赵老师'}}
一对多关系
Teacher
package com.pengshiyu.mybatis.entity;
import java.util.List;
public class Teacher {
private int id;
private String name;
private List students;
public List getStudents() {
return students;
}
public void setStudents(List students) {
this.students = students;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", name='" + name + '\'' +
", students=" + students +
'}';
}
}
TeacherMapper
查询一次
select t.id tid, t.name tname, s.id sid, s.name sname
from teachers t left join students s
on t.id = s.teacher_id
where t.id = #{id}
查询两次
select *
from teachers
where id = #{id}
select * from students where teacher_id = #{id}
mybatis-config.xml
TeacherDao
package com.pengshiyu.mybatis.dao;
import com.pengshiyu.mybatis.entity.Student;
import com.pengshiyu.mybatis.entity.Teacher;
import com.pengshiyu.mybatis.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
import java.util.List;
public class TeacherDao {
public Teacher selectOne(int id) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
Teacher teacher = session.selectOne(
"com.pengshiyu.mybatis.entity.TeacherMapper.selectOneTeacher", id);
session.close();
return teacher;
}
}
package com.pengshiyu.mybatis.test;
import com.pengshiyu.mybatis.dao.StudentDao;
import com.pengshiyu.mybatis.dao.TeacherDao;
import com.pengshiyu.mybatis.entity.Student;
import com.pengshiyu.mybatis.entity.Teacher;
import java.io.IOException;
import java.util.List;
public class Demo {
public static void main(String[] args) throws IOException {
TeacherDao teacherDao = new TeacherDao();
Teacher teacher = teacherDao.selectOne(1);
System.out.println(teacher);
for(Student student: teacher.getStudents()){
System.out.println(student);
}
}
}
输出
Teacher{id=1, name='王老师', students=[
Student{id=1, name='宋江', teacher=null},
Student{id=2, name='李逵', teacher=null}
]
}
Student{id=1, name='宋江', teacher=null}
Student{id=2, name='李逵', teacher=null}
动态 SQL
根据不同的查询条件,生成不同的 sql
select * from students
name = #{name}
sql:
select * from students WHERE name = ?
package com.pengshiyu.mybatis.dao;
import com.pengshiyu.mybatis.entity.Student;
import com.pengshiyu.mybatis.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StudentDao {
public List selectAllStudent(String name) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
Map map = new HashMap();
map.put("name", name);
List students = session.selectList(
"com.pengshiyu.mybatis.entity.StudentMapper.selectAllStudent",
map
);
session.close();
return students;
}
}
package com.pengshiyu.mybatis.test;
import com.pengshiyu.mybatis.dao.StudentDao;
import com.pengshiyu.mybatis.entity.Student;
import java.io.IOException;
import java.util.List;
public class Demo {
public static void main(String[] args) throws IOException {
StudentDao studentDao = new StudentDao();
List students = studentDao.selectAllStudent("宋江");
for(Student student: students){
System.out.println(student);
}
}
}