概念
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。
优点:
1.简化JDBC的开发
2.能够更好的完成ORM(对象关系映射)是指类和表的关系,是属性和字段值的关系
核心组件
核心配置文件: mybatis-config.xml,里面写数据源,事务,映射文件
映射文件 : XxxMapper.xml,里面写了大量的SQL
SqlSessionFactory : 是SQL的会话,用来执行SQL
SqlSession : 是SQL的会话,用来执行SQL
ORM : 对象关系的自动映射, 把car表里的字段的值查出来,一个一个,给Car类里的属性赋值
开发
创建新的module,修改pom,添加mybatis的jar包坐标
<dependencies>
<!--mybatis依赖包-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!--jdbc依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
</dependencies>
创建核心配置文件 : 数据源 , 事务 , 映射文件
<?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">
<!-- mybatis的核心配置文件 -->
<configuration>
<environments default="test">
<environment id="test">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai" />
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
创建核心映射文件 : 存大量的SQL
<?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">
<!--这是mybatis的映射文件,用来写大量的SQL
namespace属性是每个映射文件的唯一标识
-->
<mapper namespace="userMapperNS">
<!--查询user表里的所有数据
id属性是每条SQL的唯一标识
resultType属性用来完成ORM,把表里每个字段的值 自动映射给 类里的属性
-->
<select id="getAll" resultType="cn.tedu.pojo.User">
select * from user
</select>
<!--查询id=1的用户信息 resultType需要指定一个类的全路径-->
<select id="getById" resultType="cn.tedu.pojo.User">
select * from user where id=1
</select>
</mapper>
修改核心配置文件,引入映射文件
<!-- 用来引入映射文件 -->
<mappers>
<mapper resource="UserMapper.xml"></mapper>
</mappers>
创建User类
package cn.tedu.pojo;
//为了 封装User表里的每个字段的值
//要求:类名和表名对应,属性名和字段名一致
public class User {
private Integer id ;
private String name ;
private String addr ;
private Integer age ;
//set get toString
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", addr='" + addr + '\'' +
", age=" + age +
'}';
}
}
创建测试类
package cn.tedu.mybatis;
import cn.tedu.pojo.User;
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.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
//测试 mybatis
public class Test1 {
@Test
public void getAll() throws IOException {
//1,读取核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2,创建会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3,打开SQL会话
SqlSession session = factory.openSession();
//4,执行SQL -- 定位SQL的方式是namespace的值.id的值
List<User> list = session.selectList("userMapperNS.getAll");
//5,遍历list并打印
for (User u : list) {
System.out.println(u);
}
//Mybatis为了提高查询效率,会提供缓存的技术--减少了和数据库的交互次数
//当第一次查询数据时,缓存中当然没有,直接发起SQL查询了数据库,把数据存入缓存
//第二次查询 相同的数据时,先去查缓存,有就直接用,没有再去查数据库
//这是Mybatis默认就已经开启的一级缓存/SqlSession级别,必须是同一个SqlSession。
List<User> list2 = session.selectList("userMapperNS.getAll");
//5,遍历list并打印
for (User u : list2) {
System.out.println(u);
}
//根据id查询,selectOne()只返回一个结果
User u = session.selectOne("userMapperNS.getById");
System.out.println(u);
}
}
Mybatis
好处
目前都是xml配置文件的使用方式,当执行SQL,只能自己使用namespace的值,id的值,定位sql
入门案例
需求:
获取所有dept表里的数据
创建deptDao接口
package cn.tedu.dao;
import cn.tedu.pojo.Dept;
import java.util.List;
//修饰符 返回值 方法名(参数列表)
public interface DeptDao {
List<Dept> getAll(); //获取所有dept表里的数据
}
创建dept类
package cn.tedu.pojo;
//完成ORM,自动实现把dept表里字段的值 封装给不同属性
public class Dept {
private Integer id;//描述dept表里的id字段
private String dname;//描述dept表里的dname字段
private String loc;//描述dept表里的loc字段
//set get toString
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept{" +
"id=" + id +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
}
创建DeptMapper.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属性用来作为mapper文件的唯一标识
namespace属性的值是 接口的全路径
-->
<mapper namespace="cn.tedu.dao.DeptDao">
<!--select用来标记着这是一个查询的SQL语句
id属性是SQL的唯一标识
id属性的值是 接口里对应的方法名
resultType属性的值是 要把查询结果封装给哪个类的全路径
-->
<select id="getAll" resultType="cn.tedu.pojo.Dept">
select * from dept
</select>
</mapper>
修改核心配置文件,把deptMapper.xml 引进来
<!-- 用来引入映射文件 ,底层维护了MapperRegistry,用来存各种Mapper文件-->
<mappers>
<mapper resource="UserMapper.xml"></mapper>
<mapper resource="DeptMapper.xml"></mapper>
</mappers>
测试类
//测试接口的方式开始
@Test
public void inter() throws IOException {
//1,读取核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2,创建会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3,开启会话
SqlSession session = factory.openSession();
//4,执行SQL -- 参数是接口文件的class对象
DeptDao dao = session.getMapper(DeptDao.class);//获取指定的接口
List<Dept> list = dao.getAll();//定位到了SQL
//5,遍历打印
for (Dept d : list) {
System.out.println(d);
}
}
练习Mybatis接口开发方式
需求
按照id查询dept的数据
dept类
package cn.tedu.pojo;
//完成ORM,自动实现把dept表里字段的值 封装给不同属性
public class Dept {
private Integer id;//描述dept表里的id字段
private String dname;//描述dept表里的dname字段
private String loc;//描述dept表里的loc字段
//set get toString
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept{" +
"id=" + id +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
}
Mybatis核心配置文件
<?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">
<!--这个文件,是mybatis框架的核心配置文件,都配置了数据源,事务,映射文件-->
<configuration>
<environments default="test">
<!--配置数据源,事务-->
<environment id="test">
<!--配置了事务,使用jdbc提供的事务-->
<transactionManager type="JDBC"></transactionManager>
<!--配置了数据源,指定连接数据库的4个参数-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai" />
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 用来引入映射文件 ,底层维护了MapperRegistry,用来存各种Mapper文件-->
<mappers>
<mapper resource="UserMapper.xml"></mapper>
<mapper resource="DeptMapper.xml"></mapper>
</mappers>
</configuration>
Mybatis映射文件
<?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属性用来作为mapper文件的唯一标识
namespace属性的值是 接口的全路径
-->
<mapper namespace="cn.tedu.dao.DeptDao">
<!--select用来标记着这是一个查询的SQL语句
id属性是SQL的唯一标识
id属性的值是 接口里对应的方法名
resultType属性的值是 要把查询结果封装给哪个类的全路径
-->
<select id="getAll" resultType="cn.tedu.pojo.Dept">
select * from dept
</select>
<!--按照id查询dept的数据
ID属性的值=接口中的方法名
-->
<select id="getById" resultType="cn.tedu.pojo.Dept">
SELECT * FROM DEPT WHERE ID=1
</select>
</mapper>
测试
package cn.tedu.mybatis;
import cn.tedu.dao.DeptDao;
import cn.tedu.pojo.Dept;
import cn.tedu.pojo.User;
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.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
//测试 mybatis
public class Test1 {
SqlSessionFactory factory ;
//测试接口的方式开始
//@BeforeEach在执行@Test前执行,以下两步代码重复出现,提取出来,提高代码的复用性
@BeforeEach
public void init() throws IOException {
//1,读取核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2,创建会话工厂
factory = new SqlSessionFactoryBuilder().build(in);
}
//按照id获取数据
@Test
public void getById() {
//1,开启会话
SqlSession session = factory.openSession();
//2,执行接口中的方法
DeptDao dao = session.getMapper(DeptDao.class);//获取指定的接口文件
Dept d = dao.getById();//好像是调用了接口里的方法,本质上已经找到了mapper里的sql了
System.out.println(d);
}
@Test
public void inter() throws IOException {
//3,开启会话
SqlSession session = factory.openSession();
//4,执行SQL -- 参数是接口文件的class对象
DeptDao dao = session.getMapper(DeptDao.class);//获取指定的接口
List<Dept> list = dao.getAll();//定位到了SQL
//5,遍历打印
for (Dept d : list) {
System.out.println(d);
}
}
//测试xml的方式开始
@Test
public void getAll() throws IOException {
//1,读取核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2,创建会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3,打开SQL会话
SqlSession session = factory.openSession();
//4,执行SQL -- 定位SQL的方式是namespace的值.id的值
List<User> list = session.selectList("userMapperNS.getAll");
//5,遍历list并打印
for (User u : list) {
System.out.println(u);
}
//Mybatis为了提高查询效率,会提供缓存的技术--减少了和数据库的交互次数
//当第一次查询数据时,缓存中当然没有,直接发起SQL查询了数据库,把数据存入缓存
//第二次查询 相同的数据时,先去查缓存,有就直接用,没有再去查数据库
//这是Mybatis默认就已经开启的一级缓存/SqlSession级别,必须是同一个SqlSession。
List<User> list2 = session.selectList("userMapperNS.getAll");
//5,遍历list并打印
for (User u : list2) {
System.out.println(u);
}
//根据id查询,selectOne()只返回一个结果
User u = session.selectOne("userMapperNS.getById");
System.out.println(u);
}
}