MyBatis 简介
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,是一个基于Java的持久层框架。
- 持久层: 可以将业务数据存储到磁盘,具备长期存储能力,只要磁盘不损坏,在断电或者其他情况下,重新开启系统仍然可以读取到这些数据。
- 优点: 可以使用巨大的磁盘空间存储相当量的数据,并且很廉价
- 缺点:慢(相对于内存而言)
为什么使用 MyBatis
在我们传统的 JDBC 中,我们除了需要自己提供 SQL 外,还必须操作 Connection、Statment、ResultSet,不仅如此,为了访问不同的表,不同字段的数据,我们需要些很多雷同模板化的代码,闲的繁琐又枯燥。
而我们在使用了 MyBatis 之后,只需要提供 SQL 语句就好了,其余的诸如:建立连接、操作 Statment、ResultSet,处理 JDBC 相关异常等等都可以交给 MyBatis 去处理,我们的关注点于是可以就此集中在 SQL 语句上,关注在增删改查这些操作层面上。
并且 MyBatis 支持使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
搭建 MyBatis 环境:https://github.com/mybatis/mybatis-3/releases中下载mybatis 的jar包
第一个MyBatis程序:
1.创建java项目:
2.导入数据库:
create database mybatis;
user mybatis;
CREATE TABLE student(
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
studentID int(11) NOT NULL UNIQUE,
name varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected (0.15 sec)
INSERT INTO student VALUES(1,1,"我是你爸爸");
INSERT INTO student VALUES(2,2,"我是你爸爸");
INSERT INTO student VALUES(3,3,"我是你爸爸");
3.项目里,新建lib文件,和src同级,导入jar包,并标记为库:
mybatis-3.5.2.jar
mysql-connector-java-8.0.18.jar
4.创建实体类Student:
package pojo;
/**
* Student实体类
* @author lenovo
*/
public class Student {
int id;
int studentID;
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
5.配置mybatis-config.xml文件:映射文件就是刚才的实体类Student的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>
<!-- 别名 -->
<typeAliases>
<package name="pojo"/>
</typeAliases>
<!-- 数据库环境 -->
<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://localhost:3306/mybatis?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 映射文件 -->
<mappers>
<mapper resource="pojo/Student.xml"/>
</mappers>
</configuration>
6.创建Student.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="dao">
<!-- 由于在mybatis-config.xml里配置了 <typeAliases> 别名,所以在这里的 resultType 可以直接写 Student,而不用写类的全限定名 pojo.Student-->
<!-- namespace 属性其实就是对 SQL 进行分类管理,实现不同业务的 SQL 隔离-->
<select id="listStudent" resultType="Student">
select * from mybatis.student
</select>
</mapper>
7.编写测试类:
package test;
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 pojo.Student;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author lenovo
*/
public class MybatisTest{
public static void main(String[] args) throws IOException {
// 根据 mybatis-config.xml 配置的信息得到 sqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 然后根据 sqlSessionFactory 得到 session
SqlSession session = sqlSessionFactory.openSession();
// 最后通过 session 的 selectList() 方法调用 sql 语句 listStudent
List<Student> listStudent = session.selectList("listStudent");
for (Student student : listStudent) {
System.out.println("ID:" + student.getId() + "NAME:" + student.getName());
}
}
}
8.运行测试类:
结果:
ID:1NAME:我是你爸爸
ID:2NAME:我是你爸爸
ID:3NAME:我是你爸爸
运行原理:
基本原理
- 应用程序找 MyBatis 要数据
- MyBatis 从数据库中找来数据
1.通过 mybatis-config.xml 定位哪个数据库(mybatis)
2.通过 Student.xml 执行对应的 sql 语句
3.基于 Student.xml 把返回的数据库封装在 Student 对象中
4.把多个 Student 对象装载一个 Student 集合中 - 返回一个 Student 集合
CRUN操作
1.创建实体类Student:
package pojo;
/**
* Student实体类
* @author lenovo
*/
public class Student {
int id;
int studentID;
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.配置mybatis-config.xml文件:映射文件就是刚才的实体类Student的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>
<!-- 别名 -->
<typeAliases>
<package name="pojo"/>
</typeAliases>
<!-- 数据库环境 -->
<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://localhost:3306/mybatis?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 映射文件 -->
<mappers>
<mapper resource="pojo/Student.xml"/>
</mappers>
</configuration>
3.配置Student.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="pojo">
<!-- parameterType:要求输入参数的类型-->
<!-- resultType:输出的类型-->
<select id="listStudent" resultType="Student">
select * from mybatis.student
</select>
<insert id="addStudent" parameterType="Student">
insert into mybatis.student (id, studentID, name) values (#{id},#{studentID},#{name})
</insert>
<delete id="deleteStudent" parameterType="Student">
delete from mybatis.student where id = #{id}
</delete>
<select id="getStudent" parameterType="_int" resultType="Student">
select * from mybatis.student where id= #{id}
</select>
<update id="updateStudent" parameterType="Student">
update mybatis.student set name=#{name} where id=#{id}
</update>
</mapper>
4.实现增删改查
package test;
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 pojo.Student;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyBatisTest {
public static void main(String[] args) throws IOException {
// 根据 mybatis-config.xml 配置的信息得到 sqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 然后根据 sqlSessionFactory 得到 session
SqlSession session = sqlSessionFactory.openSession();
// 增加学生 加了一个 ID 和 studentID 都为 4,名字为“新增加的学生” 的学生
Student student1 = new Student();
student1.setId(4);
student1.setStudentID(4);
student1.setName("新增加的学生");
session.insert("addStudent", student1);
// 删除学生 删除了 ID = 1 的学生
Student student2 = new Student();
student2.setId(1);
session.delete("deleteStudent", student2);
// 获取学生 获取了 ID = 2的学生
Student student3 = session.selectOne("getStudent", 2);
// 修改学生 将 ID = 2 的学生的名字修改为 “修改的学生”
student3.setName("修改的学生");
session.update("updateStudent", student3);
// 最后通过 session 的 selectList() 方法调用 sql 语句 listStudent
List<Student> listStudent = session.selectList("listStudent");
for (Student student : listStudent) {
System.out.println("ID:" + student.getId() + ",NAME:" + student.getName());
}
// 提交修改 来提交事务,也可以简单理解为更新到数据库
session.commit();
// 关闭 session
session.close();
}
}
5.运行测试类MyBatisTest
运行结果:
ID:2,NAME:修改的学生
ID:3,NAME:我是你爸爸
ID:4,NAME:新增加的学生
模糊查询:
1.创建实体类Student:
package pojo;
/**
* Student实体类
* @author lenovo
*/
public class Student {
int id;
int studentID;
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.配置mybatis-config.xml文件:映射文件就是刚才的实体类Student的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>
<!-- 别名 -->
<typeAliases>
<package name="pojo"/>
</typeAliases>
<!-- 数据库环境 -->
<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://localhost:3306/mybatis?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 映射文件 -->
<mappers>
<mapper resource="pojo/Student.xml"/>
</mappers>
</configuration>
3.配置Student.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="pojo">
<!-- parameterType:要求输入参数的类型-->
<!-- resultType:输出的类型-->
<select id="findStudentByName" parameterType="String" resultType="Student">
SELECT * FROM mybatis.student WHERE name LIKE '%${value}%'
</select>
</mapper>
4.运行测试类
package test;
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 org.junit.Test;
import pojo.Student;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author lenovo
*/
public class MyBatisTest {
@Test
public void test() throws IOException {
// 根据 mybatis-config.xml 配置的信息得到 sqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 然后根据 sqlSessionFactory 得到 session
SqlSession session = sqlSessionFactory.openSession();
// 模糊查询
List<Student> students = session.selectList("findStudentByName", "爸爸");
for (Student student : students) {
System.out.println("ID:" + student.getId() + ",NAME:" + student.getName());
}
}
}
5.运行测试类:
结果:
ID:3,NAME:我是你爸爸
多条件查询
1.创建实体类Student:
package pojo;
/**
* Student实体类
* @author lenovo
*/
public class Student {
int id;
int studentID;
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.配置mybatis-config.xml文件:映射文件就是刚才的实体类Student的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>
<!-- 别名 -->
<typeAliases>
<package name="pojo"/>
</typeAliases>
<!-- 数据库环境 -->
<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://localhost:3306/mybatis?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 映射文件 -->
<mappers>
<mapper resource="pojo/Student.xml"/>
</mappers>
</configuration>
3.配置Student.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="pojo">
<!-- parameterType:要求输入参数的类型-->
<!-- resultType:输出的类型-->
<select id="listCategoryByIdAndName" parameterType="map" resultType="Student">
select * from mybatis.student where id> #{id} and name like concat('%',#{name},'%')
</select>
</mapper>
4.创建测试类:进入junit.jar包
package test;
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 org.junit.Test;
import pojo.Student;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author lenovo
*/
public class MyBatisTest {
@Test
public void test() throws IOException {
// 根据 mybatis-config.xml 配置的信息得到 sqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 然后根据 sqlSessionFactory 得到 session
SqlSession session = sqlSessionFactory.openSession();
// 因为是多个参数,而selectList方法又只接受一个参数对象,所以需要把多个参数放在Map里,然后把这个Map对象作为参数传递进去
// 查询id>1且名字内有‘我是你爸’的名字
Map<String,Object> params = new HashMap<>();
params.put("id", 1);
params.put("name", "我是你爸");
List<Student> cs = session.selectList("listCategoryByIdAndName",params);
for (Student c : cs) {
System.out.println(c.getName());
}
}
}
5.运行测试类:
结果:
我是你爸爸
- parameterType: 就是用来在 SQL 映射文件中指定输入参数类型的,可以指定为基本数据类型(如 int、float 等)、包装数据类型(如 String、Interger 等)以及用户自己编写的 JavaBean 封装类
- resultType: 在加载 SQL 配置,并绑定指定输入参数和运行 SQL 之后,会得到数据库返回的响应结果,此时使用 resultType 就是用来指定数据库返回的信息对应的 Java 的数据类型。
- “#{}” : 在传统的 JDBC 的编程中,占位符用 “?” 来表示,然后再加载 SQL 之前按照 “?” 的位置设置参数。而 “#{}” 在 MyBatis 中也代表一种占位符,该符号接受输入参数,在大括号中编写参数名称来接受对应参数。当 “#{}” 接受简单类型时可以用
value
或者其他任意名称来获取。 - “${}” : 在 SQL 配置中,有时候需要拼接 SQL 语句(例如模糊查询时),用 “#{}” 是无法达到目的的。在 MyBatis 中,“${}” 代表一个 “拼接符号” ,可以在原有 SQL 语句上拼接新的符合 SQL 语法的语句。使用 “${}” 拼接符号拼接 SQL ,会引起 SQL 注入,所以一般不建议使用 “${}”。
- MyBatis 使用场景: 在进行 MyBatis 开发时,大部分精力都放在了 SQL 映射文件上。 MyBatis 的特点就是以 SQL 语句为核心的不完全的 ORM(关系型映射)框架。与 Hibernate 相比,Hibernate 的学习成本比较高,而 SQL 语句并不需要开发人员完成,只需要调用相关 API 即可。这对于开发效率是一个优势,但是缺点是没办法对 SQL 语句进行优化和修改。而 MyBatis 虽然需要开发人员自己配置 SQL 语句,MyBatis 来实现映射关系,但是这样的项目可以适应经常变化的项目需求。所以使用 MyBatis 的场景是:对 SQL 优化要求比较高,或是项目需求或业务经常变动。