MyBatis 第一個程序
MyBatis 是基於 Java 的數據持久層框架
持久化:數據從瞬時狀態變爲持久狀態
持久層:完成持久化工作的代碼塊 DAO
簡而言之:
MyBatis 將數據存入數據庫中,從數據庫中取數據
通過框架可以減少重複代碼,提高開發效率
MyBatis 是一個半自動化的 ORM 框架
Object Relationship Mapping
文檔:
https://mybatis.org/mybatis-3/zh/index.html
1、依賴
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
2、配置數據庫
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/data"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="StudentMapper.xml"/>
</mappers>
</configuration>
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
<?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.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectStudent" resultType="com.pengshiyu.mybatis.entity.Student">
select * from students where id = #{id}
</select>
</mapper>
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
<?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.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectStudent" resultType="com.pengshiyu.mybatis.entity.Student">
select * from students where id = #{id}
</select>
<select id="selectAllStudent" resultType="com.pengshiyu.mybatis.entity.Student">
select * from students
</select>
<insert id="insertStudent" parameterType="com.pengshiyu.mybatis.entity.Student">
insert into students(name, age) values(#{name}, #{age})
</insert>
<update id="updateStudent" parameterType="com.pengshiyu.mybatis.entity.Student">
update students set name = #{name}, age = #{age} where id = #{id}
</update>
<delete id="deleteStudent">
delete from students where id = #{id}
</delete>
</mapper>
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<Student> selectAll() throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
List<Student> 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<Student> 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
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 加載數據庫配置 -->
<properties resource="db.properties" />
<settings>
<!-- 打印sql日誌 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="StudentMapper.xml"/>
</mappers>
</configuration>
2、別名配置
<configuration>
<typeAliases>
<!-- 指定單個類的別名 -->
<typeAlias type="com.pengshiyu.mybatis.entity.Student" alias="Student"/>
<!-- 指定整個包下的類都是別名 -->
<package name="com.pengshiyu.mybatis.entity"/>
</typeAliases>
</configuration>
使用別名
<mapper namespace="com.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectAllStudent" resultType="Student">
select * from students
</select>
</mapper>
屬性名和列名不一致
MyBatis 會根據列名取賦值,會將列名轉爲小寫
1、爲列名指定別名
<mapper namespace="com.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectStudent" resultType="Student">
select id, name, age as old from students where id = #{id}
</select>
</mapper>
2、使用結果映射類型
<mapper namespace="com.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectStudent" resultMap="StudentMap">
select id, name, age from students where id = #{id}
</select>
<resultMap id="StudentMap" type="Student">
<!-- id爲主鍵 -->
<id column="id" property="id" />
<!-- column是數據庫表的列名,property是實體類屬性名 -->
<result column="name" property="name"/>
<result column="age" property="age"/>
</resultMap>
</mapper>
分頁的實現
1、sql 中實現
如果將數據看做下標從 0 開始,那麼就是數據切片 [startIndex, pageSize)
<mapper namespace="com.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectAllStudent" parameterType="Map" resultType="Student">
select * from students limit #{offset}, #{limit}
</select>
</mapper>
public class StudentDao {
public List<Student> selectAll(int currentPage, int pageSize) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("offset", (currentPage - 1) * pageSize);
map.put("limit", pageSize);
List<Student> 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<Student> students = studentDao.selectAll(2 , 2);
for(Student student: students){
System.out.println(student);
}
}
}
2、使用 RowBounds
<mapper namespace="com.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectAllStudent" resultType="Student">
select * from students
</select>
</mapper>
import org.apache.ibatis.session.RowBounds;
public class StudentDao {
public List<Student> selectAll(int currentPage, int pageSize) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
RowBounds rowBounds = new RowBounds((currentPage - 1) * pageSize, pageSize);
List<Student> 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<Student> getList();
}
修改配置文件
<configuration>
<mappers>
<!-- <mapper resource="StudentMapper.xml"/>-->
<mapper class="com.pengshiyu.mybatis.dao.IStudentDao"/>
</mappers>
</configuration>
測試使用
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<Student> 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)按結果嵌套
查詢一次
<mapper namespace="com.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectAllStudent" resultMap="StudentMap">
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
</select>
<resultMap id="StudentMap" type="Student">
<!-- 主鍵 -->
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<!-- 關聯對象-->
<association property="teacher" javaType="Teacher">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
</association>
</resultMap>
</mapper>
- 按查詢嵌套
會查詢 n 次,n 是 Student 數量
<mapper namespace="com.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectAllStudent" resultMap="StudentTeacher">
select * from students
</select>
<resultMap id="StudentTeacher" type="Student">
<!-- 關聯對象-->
<association property="teacher" column="teacher_id"
javaType="Teacher" select="getTeacher">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
</association>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teachers where id = #{id}
</select>
</mapper>
4、引入映射文件
mybatis-config.xml
<configuration>
<typeAliases>
<package name="com.pengshiyu.mybatis.entity"/>
</typeAliases>
<mappers>
<mapper resource="StudentMapper.xml"/>
</mappers>
</configuration>
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<Student> selectAll() throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
List<Student> 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<Student> 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<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> 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
查詢一次
<mapper namespace="com.pengshiyu.mybatis.entity.TeacherMapper">
<select id="selectOneTeacher" resultMap="TeacherStudent">
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>
<resultMap id="TeacherStudent" type="Teacher">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
<!-- 關聯集合 -->
<collection property="students" ofType="Student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
</collection>
</resultMap>
</mapper>
查詢兩次
<mapper namespace="com.pengshiyu.mybatis.entity.TeacherMapper">
<select id="selectOneTeacher" resultMap="TeacherStudent">
select *
from teachers
where id = #{id}
</select>
<resultMap id="TeacherStudent" type="Teacher">
<!-- 關聯集合 -->
<!-- column 是外鍵 -->
<collection property="students" column="id" ofType="Student"
select="getStudentByTeacherId">
</collection>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from students where teacher_id = #{id}
</select>
</mapper>
mybatis-config.xml
<configuration>
<typeAliases>
<package name="com.pengshiyu.mybatis.entity"/>
</typeAliases>
<mappers>
<mapper resource="TeacherMapper.xml"/>
</mappers>
</configuration>
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
<mapper namespace="com.pengshiyu.mybatis.entity.StudentMapper">
<select id="selectAllStudent" resultType="Student">
select * from students
<where>
<if test="name != null">
name = #{name}
</if>
</where>
</select>
</mapper>
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<Student> selectAllStudent(String name) throws IOException {
SqlSession session = MyBatisUtil.getSqlSession();
Map<String, String> map = new HashMap<>();
map.put("name", name);
List<Student> 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<Student> students = studentDao.selectAllStudent("宋江");
for(Student student: students){
System.out.println(student);
}
}
}