Mybatis框架学习
Mybatis介绍
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis
避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis
可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old
Java Objects,普通老式 Java 对象)为数据库中的记录。
Mybatis简单使用
1.初始化SqlSessionFactory对象:
1.SqlSessionFactory对象:
需要从核心配置文件中获得,因此我们创建SqlSessionFactory对象时需要先配置一个Mybatis核心配置文件,过程如下:
1>.创建一个模板:建议最好去官网上找模板Mybatis配置模板
2.效果试图和创建Mybatis过程:
3.创建后的文件:
2.核心配置文件如下:
<?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文件,路径从类路径的根目录开始 -->
<properties resource="jdbc.properties" />
<settings>
<!-- 开启将数据库中下划线连接的字段自动映射为Java的小驼峰命名 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- 定义类型别名,在xxxMapper.xml文件中就可以用别名代替很长的类名 -->
<typeAliases>
<!-- 单个类配置别名 -->
<!-- <typeAlias type="com.lanou3g.mybatis.bean.User" alias="User" />-->
<!-- 统一配置某个包下所有类的别名, 会使用 Bean 的首字母小写的类名来作为它的别名。 -->
<package name="com.lanou3g.mybatis.bean" />
</typeAliases>
<!-- 配置不同环境的参数 -->
<environments default="development">
<!-- 开发环境数据库、事务配置 -->
<environment id="development">
<!-- 事务管理使用JDBC的事务 -->
<transactionManager type="JDBC"/>
<!-- 配置开发环境数据源 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 将所有driver.开头的参数,附加到url属性的值后面上 -->
<property name="driver.characterEncoding" value="utf8"/>
</dataSource>
</environment>
</environments>
<!-- 将mapper SQL映射文件包含进来 -->
<mappers>
<!-- 将通过XML方式配置的mapper引入进来 -->
<mapper resource="mapper/userMapper.xml"/>
<!-- 将通过注解方式配置的mapper引入进来 -->
<!-- <mapper class="com.lanou3g.mybatis.mapper.UserMapper" />-->
<!-- 将com.lanou3g.mybatis.mapper包下所有通过注解方式配置的mapper引入进来 -->
<!-- <package name="com.lanou3g.mybatis.mapper"/>-->
</mappers>
</configuration>
1.构建对象:
@Test
public void testXml() throws IOException {
String xmlPath = "mybatis_config.xml";
InputStream inputStream = Resources.getResourceAsStream(xmlPath);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
System.out.println(sessionFactory);
}
2.创建SqlSession对象
通过上步的SqlSessionFactory对象的创建可以获取到负责执行sql的SqlSession对象
// 3. 获取SqlSession对象,默认事务不自动提交
// SqlSession sqlSession = sqlSessionFactory.openSession();
// 获取一个自动提交事务的sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
3.用SqlSession对象从Mybatis中获取Mapper接口的实现类
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
4.编写Mapper对象的xml配置文件
和核心配置文件的步骤一样去官网找文档配置修改之后是这样,这里可以配合Fre Mybatis plugin插件使用效率更高:
<?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.lanou3g.mybatis.mapper.UserMapper">
<select id="queryAllUser" resultType="user">
select * from user
</select>
<insert id="insertUser">
insert into user (username,nick_name,email)
values (#{username},#{nickName},#{email})
</insert>
</mapper>
深入了解Mybatis
主要组件
核心配置文件的处理:
所谓的核心配置文件,就是mybatis的入口.它里面可以配置mybatis的具体参数、数据源、类型别名、关联映射文件等。
加载Mybatis配置文件的路径:
String configMybatisXmlpath = "mybatis-config.xml";
Resources
package org.apache.ibatis.io;
//Resources:所在的包.
public static InputStream getResourceAsStream(String resource) throws IOException {
return getResourceAsStream((ClassLoader)null, resource);
}
public static InputStream getUrlAsStream(String urlString) throws IOException {
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
return conn.getInputStream();
}
//上面是底层常用的方法:
//例如:加载加载Mybatis配置文件
InputStream inputStream = Resources.getResourceAsStream(configurationXmlPath);
SqlSessionFactoryBuilser
主要用来创建SqlSessionFactory接口类对象.
//SqlSessionFactoryBuiler所在的包:
package org.apache.ibatis.session;
public SqlSessionFactory build(Reader reader, String environment) {
return this.build((Reader)reader, environment, (Properties)null);
}
public SqlSessionFactory build(InputStream inputStream) {
return this.build((InputStream)inputStream, (String)null, (Properties)null);
}
//上面是SqlSessionFactoryBuilser的部分底层.我们调用build方法来获得下面的SqlSessionFactory接口类对象.
//例如下面:获得SqlSessionFactory接口类对象:development表示xml中的environment的id
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"development");
SqlSessionFactory
一个SqlSessionFactory只能连接一个数据库实例,如果需要连接多个数据库,需要构建多个SqlSessionFactory对象。
在构建SqlSesssionFactory时可以指定environment的id,表示使用指定的数据源来构建factory对象
//这个是是否开启自动提交事务:入过不开启自动提交的话可能出现sql语句执行了,页成功了但
//是没有插入到数据库例如下面实例:一般我们把参数设置为true,让它自动提交事务,如果没有设置出现下面实例 // 中的错误,在实例1下面由解决方法.注意Query时开不开没关系,最好开启
SqlSession openSession((boolean autoCommit);
SqlSession openSession(Connection var1);
//TransactionIsolationLevel是一个枚举类,事务隔离
// NONE(0),
//READ_COMMITTED(2),
//READ_UNCOMMITTED(1),
//REPEATABLE_READ(4),
//SERIALIZABLE(8);
SqlSession openSession(TransactionIsolationLevel level);
// ExecutorType枚举类
//SIMPLE,
//REUSE,
//BATCH; 最常用的试着个,Mybatis缓冲,下面我们会总结到
SqlSession openSession(ExecutorType var1);
SqlSession openSession(ExecutorType var1, boolean var2);
SqlSession openSession(ExecutorType var1, TransactionIsolationLevel var2);
SqlSession openSession(ExecutorType var1, Connection var2);
Configuration getConfiguration();
关于Mybatis的TransactionIsolationLevel枚举类的探究,事务隔离级别:
隔离级别:一个事务必须与由其他事务进行的资源或数据更改相隔离的程度。隔离级别从允许的并发副作用(例如,脏读或虚拟读取)的角度进行描述。
none:
read uncommitted | 1 未提交读
read committed | 2 已提交读
repeatable read | 4 可重复读
serializable | 8 可序列化
实例1:
@Test
public void testPaperGirl() {
String configurationXmlPath = "mybatis-config.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(configurationXmlPath);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//注意这里要开启事务:坑
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
KingMapper mapper = sqlSession.getMapper(KingMapper.class);
List<Girl> girlList = new ArrayList<>();
Collections.addAll(girlList, new Girl("木兰", 2), new Girl("伽罗", 2));
int count = 0;
List<BatchResult> batchResults = null;
for(Girl girl : girlList){
mapper.insertPaperGir(girl);
count ++ ;
if(count % 2 == 0){
batchResults = sqlSession.flushStatements();
count = 0 ;
}
}
for(BatchResult batchResult : batchResults){
int[] updateCounts = batchResult.getUpdateCounts();
for(int updateCount : updateCounts){
System.out.println(updateCount);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
结果如下:
但是数据库中并没有插入:
解决办法有两种
//解决方法一:
SqlSession openSession(true);
//解决方法二
@Test
public void testPaperGirl() {
String configurationXmlPath = "mybatis-config.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(configurationXmlPath);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//注意这里要开启事务:坑
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
KingMapper mapper = sqlSession.getMapper(KingMapper.class);
List<Girl> girlList = new ArrayList<>();
Collections.addAll(girlList, new Girl("木兰", 2), new Girl("伽罗", 2));
int count = 0;
List<BatchResult> batchResults = null;
for(Girl girl : girlList){
mapper.insertPaperGir(girl);
count ++ ;
if(count % 2 == 0){
batchResults = sqlSession.flushStatements();
count = 0 ;
}
}
for(BatchResult batchResult : batchResults){
int[] updateCounts = batchResult.getUpdateCounts();
for(int updateCount : updateCounts){
System.out.println(updateCount);
}
}
//在这里加事务提交:
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
解决后结果:
SqlSession
一个SqlSession对象代表一次到数据的会话,该对象有一下功能:
- 获取Mapper实现类
- 管理事务操作
- 注意: SqlSession对象是非线程安全的,在多线程环境下,建议不要作为类的实例属性来用。
Mapper接口类:
Mapper
-
Mapper接口类
定义了增删盖查的方法。注意,必须是接口类型,而且方法只需要定义就可以了。
-
Mapper配置文件
Mapper配置文件中就是负责实现接口中的方法,它定义了具体要执行什么SQL语句,如何映射结果集。
- 配置文件中select、delete、update、insert标签的id必须是对应接口中的方法名。
- mapper文件的namespace属性需要对应Mapper接口的完全类型限定名。
深入Mybatis核心配置文件
深入Mybatis映射配置文件
CRUD语句定义
接口中的源码
public interface KingMapper {
List<King> findKingById(int id);
int insertGirl(List<Girl> girlList);
int insertPaperGir(Girl girl);
}
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.lanou.mapper.KingMapper">
<resultMap id="kingMap" type="com.lanou.bean.King">
<id column="k_id" property="kId"/>
<result column="k_name" property="kName"/>
<association property="queen" javaType="com.lanou.bean.Queen" resultMap="queenMap"/>
<collection property="girls" ofType="com.lanou.bean.Girl" resultMap="girlMap"/>
</resultMap>
<resultMap id="girlMap" type="com.lanou.bean.Girl">
<id property="gId" column="g_id"/>
<result property="kId" column="k_id"/>
<result property="gName" column="g_name"/>
</resultMap>
<resultMap id="queenMap" type="com.lanou.bean.Queen">
<id column="q_id" property="qId"/>
<result column="k_id" property="kId"/>
<result column="q_name" property="qName"/>
</resultMap>
<insert id="insertGirl">
insert into girl (g_name,k_id) values
<foreach collection="list" item="girl" separator=",">
(#{girl.gName},#{girl.kId})
</foreach>
</insert>
<insert id="insertPaperGir">
insert into girl (g_name,k_id) values(#{gName},#{kId})
</insert>
<select id="findKingById" resultMap="kingMap">
select
king.k_id k_id,
k_name,
q_id,
q_name,
g_id,
g_name
from king
left join girl
on king.k_id = girl.k_id
left join queen
on queen.k_id = king.k_id
where king.k_id = #{id};
</select>
</mapper
插入语句
普通插入语句
接口
int insertUser(User user);
xml中的配置
<insert id="insertUser">
insert into user (username,nick_name,email)
values (#{username},#{nickName},#{email})
</insert>
如何返回数据库自增的ID
java源代码之接口中
public interface GirlMapper {
int insertGirl(Girl girl);
}
xml中
<!-- 给insert语句添加useGeneratedKeys、keyProperty后,mybatis会将自增的id值直接赋值到传进来的user对象的id属性上
useGeneratedKeys: 指定需要获取数据库自增的id
keyProperty: 指定自增地段的名称
ps:只对update和insert语句使用
-->
<insert id="insertGirl" useGeneratedKeys="true" keyProperty="gId" >
insert into girl (g_name,k_id)
values(#{gName},#{kId})
</insert>
测试
@Test
public void testGirl(){
String configMybatisXmlpath = "mybatis-config.xml";
try {
InputStream resourceAsStream = Resources.getResourceAsStream(configMybatisXmlpath);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession(true);
GirlMapper girlMapper = sqlSession.getMapper(GirlMapper.class);
Girl girl = new Girl("香蛋",1);
int i = girlMapper.insertGirl(girl);
System.out.println(girl.getGId());
} catch (IOException e) {
e.printStackTrace();
}
}
结果
ps:
keyColumn="":(仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。
keyProperty="" :给insert语句添加useGeneratedKeys、keyProperty后,mybatis会将自增的id值直接赋值到传进来的user对象的id属性上:
useGeneratedKeys: 指定需要获取数据库自增的id
keyProperty: 指定自增地段的名称
只对update和insert语句使用
删除语句
接口中
void deleteUserById(Integer id);
xml中的配置:
<delete id="deleteUserById">
delete from user where id = #{id}
</delete>
更新语句
接口中:
void updateUser(User user);
XML配置中
<update id="updateUser">
update user set password = #{password} where id = #{id}
</update>
ps:
插入和更新删除需要:
SqlSession sqlSession = sessionFactory.openSession(true);
接口中的参数如果传递到SQL中
简单类型参数
接口中
void deleteUserById(Integer id);
xml配置
<delete id="deleteUserById">
delete from user where id = #{id}
</delete>
引用类型参数
接口中
int insertUser(User user);
<!--这里注意取参数直接#+实体类字段名-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into user (username,nick_name,email)
values (#{username},#{nickName},#{email})
</insert>
当接口中参数和XML配置取值时名称不一样时
ps:现在Mybatis版本中的不存在这个问题
在接口中的参数前加注解
User queryUserById(@Param("id") Integer xxxxxxxId);
在XML中取值时用注解指定的名称
<select id="queryUserById" resultType="user">
select * from user where id = #{id}
</select>
例如:
接口中的java代码:
public interface GirlMapper {
Girl queryGirl(Integer sid);
}
xml中的配置:
<select id="queryGirl" resultType="com.lanou.bean.Girl">
select * from girl where g_id = #{gId}
</select>
运行的结果:
#{}与${}的区别
- 它俩都可以获取接口调用中传递过来的参数
- #{}会将参数作为占位符,使用预编译语句(PreparedStatement)执行
- 会 直 接 用 实 际 参 数 替 换 {}会直接用实际参数替换 会直接用实际参数替换{}, 参数可以作为SQL的一部分。
接口中的配置:
public interface GirlMapper {
Girl queryGirl(Integer sid);
}
xml配置:
<select id="queryGirl" resultType="com.lanou.bean.Girl">
select * from girl where g_id = #{gId}
</select>
#的运行结果:
结果集如何映射
ResultType方式
ResultType方式适用于数据库结果集可以直接映射成一个Java类的情况
ResultMap方式
ResultMap方式适用于复杂的结果集映射,比如数据库返回的结果集中的列名和JavaBean无法一一对应,或者对象间存在一对一、一对多关联映射时。
解决数据库列名与Java类中属性名不一致的映射问题
解决一对一映射查询问题
解决一对多映射查询问题
下面是例子:
package com.lanou.bean;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Setter
@Getter
@ToString
public class Girl {
private int gId;
private int kId;
private String gName;
public Girl(){
}
public Girl(String gName ,int kId) {
this.gName = gName;
this.kId = kId;
}
}
package com.lanou.bean;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.List;
@Setter
@Getter
@ToString
public class King {
private int kId;
private String kName;
private Queen queen;
private List<Girl> girls;
}
package com.lanou.bean;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class Queen {
private int qId;
private int kId;
private String qName;
}
接口中
package com.lanou.mapper;
import com.lanou.bean.Girl;
import com.lanou.bean.King;
import java.util.List;
public interface KingMapper {
List<King> findKingById(int id);
int insertGirl(List<Girl> girlList);
int insertPaperGir(Girl girl);
}
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.lanou.mapper.KingMapper">
<resultMap id="kingMap" type="com.lanou.bean.King">
<id column="k_id" property="kId"/>
<result column="k_name" property="kName"/>
<!--这是一对一的情况-->
<association property="queen" javaType="com.lanou.bean.Queen" resultMap="queenMap"/>
<!--这是一对多的情况-->
<collection property="girls" ofType="com.lanou.bean.Girl" resultMap="girlMap"/>
</resultMap>
<resultMap id="girlMap" type="com.lanou.bean.Girl">
<id property="gId" column="g_id"/>
<result property="kId" column="k_id"/>
<result property="gName" column="g_name"/>
</resultMap>
<resultMap id="queenMap" type="com.lanou.bean.Queen">
<id column="q_id" property="qId"/>
<result column="k_id" property="kId"/>
<result column="q_name" property="qName"/>
</resultMap>
<insert id="insertGirl">
insert into girl (g_name,k_id) values
<foreach collection="list" item="girl" separator=",">
(#{girl.gName},#{girl.kId})
</foreach>
</insert>
<insert id="insertPaperGir">
insert into girl (g_name,k_id) values(#{gName},#{kId})
</insert>
<select id="findKingById" resultMap="kingMap">
select
king.k_id k_id,
k_name,
q_id,
q_name,
g_id,
g_name
from king
left join girl
on king.k_id = girl.k_id
left join queen
on queen.k_id = king.k_id
where king.k_id = #{id};
</select>
</mapper>
动态sql
条件分支SQL
-
if
mapper中:
package com.lanou.mappers; import com.lanou.bean.Student; import java.util.List; public interface StudentMqpper { List<Student> findStudent(Student condition); }
xml中:
<select id="findStudent" resultType="com.lanou.bean.Student"> select * from `student` <where> <if test="sex != null" > sex = #{sex} </if> <if test="name != null" > and name = #{name} </if> </where> </select>
测试1:
@Test public void testStudentMapper(){ String configMybatisXmlpath = "mybatis-config.xml"; try { InputStream resourceAsStream = Resources.getResourceAsStream(configMybatisXmlpath); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sessionFactory.openSession(); StudentMqpper mapper = sqlSession.getMapper(StudentMqpper.class); Student condition = new Student(); condition.setName("黄忠"); condition.setSex("男"); List<Student> studentList = mapper.findStudent(condition); for(Student student1 :studentList ){ System.out.println(student1.toString()); } } catch (IOException e) { e.printStackTrace(); } }
结果:
测试2:把setAge注释掉:
结果为:
- choose&when&otherwise
循环SQL
- forEach
两种forEach:
第一种:
实例
mapper中:
public interface KingMapper {
int insertGirl(List<Girl> girlList);
}
xml中:
<insert id="insertGirl">
insert into girl (g_name,k_id) values
<foreach collection="list" item="girl" separator=",">
(#{girl.gName},#{girl.kId})
</foreach>
</insert>
第二种:
mapper中:
public interface KingMapper {
int insertPaperGir(Girl girl);
}
xml中:
<insert id="insertPaperGir">
insert into girl (g_name,k_id) values(#{gName},#{kId})
</insert>
其他特殊SQL
- where
- set
- trim
一级缓存:
默认情况下是一级缓存,配置方法:
<setting name="localCacheScope" value="SESSION"/>
取值有两个:SESSION和STATEMENT分别对应缓存应用session会话范围和一次statement范围
验证:
mapper中:
public interface GirlsMapper {
List<Girl> queryGirls();
int insertGirl(Girl girl);
}
xml中:
<insert id="insertGirl">
insert into girl (g_name,k_id) value(#{gName},#{kId})
</insert>
<select id="queryGirls" resultType="com.lanou.bean.Girl">
select * from girl
</select>
测试:注意先不要设置自动提交,这样就能看到增删改是先对缓存的改动.提交之后才能到数据库更新数据:
@Test
public void testCache(){
String mybatisXmlpath ="mybatis-config-cache.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(mybatisXmlpath);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
GirlsMapper girlsMapper = sqlSession.getMapper(GirlsMapper.class);
List<Girl> girlList = girlsMapper.queryGirls();
System.out.println("*************" + girlList.size());
for(Girl girl : girlList){
System.out.println(girl.toString());
}
Girl girl = new Girl("香香",1);
int i = girlsMapper.insertGirl(girl);
System.out.println(i);
// sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
结果是:
然而数据库中则:
放开commit:
@Test
public void testCache(){
String mybatisXmlpath ="mybatis-config-cache.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(mybatisXmlpath);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
GirlsMapper girlsMapper = sqlSession.getMapper(GirlsMapper.class);
List<Girl> girlList = girlsMapper.queryGirls();
System.out.println("*************" + girlList.size());
for(Girl girl : girlList){
System.out.println(girl.toString());
}
Girl girl = new Girl("香香",1);
int i = girlsMapper.insertGirl(girl);
System.out.println(i);
// sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
结果:
结果很明显也很符合上面原理图
二级缓存:
开启二级缓存的方法
- 第一步,打开全局二级缓存开关
<setting name="cacheEnabled" value="true"/>
- 在具体的Mapper中开启二级缓存
<cache/>
可配置参数:
type
:cache使用的类型,默认是PerpetualCache
,这在一级缓存中提到过。eviction
: 定义回收的策略,常见的有FIFO,LRU。flushInterval
: 配置一定时间自动刷新缓存,单位是毫秒。size
: 最多缓存对象的个数。readOnly
: 是否只读,若配置可读写,则需要对应的实体类能够序列化。blocking
: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。
注意 要使用二级缓存结果集对应的POJO类必须实现序列化接口
Spring与Mybatis的整合:
1.需要的依赖:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
2.在Spring中管理SqlSessionFactory
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 设置mybatis核心配置文件路径(可选) -->
<property name="configLocation" value="classpath:/mybatis-config.xml" />
<!-- 配置mybatis xml映射文件位置(如果Mapper是用注解配置的,这里就不用设置此属性了) -->
<property name="mapperLocations" value="classpath:/mappers/*" />
</bean>
如果是注解的方式配置的Mapper,我们需要在Spring配置文件中添加mybatis的schema以支持mybatis注解扫描
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
<!-- 配置基于注解的Mapper所在包的路径 -->
<mybatis:scan base-package="org.mybatis.spring.sample.mapper" />
</beans>
或者这样配置
@Configuration
@MapperScan("org.mybatis.spring.sample.mapper")
public class AppConfig {
// ...
}
3.用Spring管理事务
和单独使用Spring时一样, 配置Spring的声明式事务就可以了,mybatis会自动参与到spring的事务中