mybatis-spring 入门到实例

入门

安装

在pom.xml中导入mybatis-spring.jar包

快速入门

要把spring和mybatis一起使用,需要定义两样东西:SqlsessionFactory 和 至少一个数据库映射器类。

SqlSessionFactoryBean 是用于创建 SqlSessionFactory 的,需要一个Datasource参数。

<!-- spring-config.xml -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" />
</bean>

假如定义了一个如下的mapper接口:

public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{userId}")User getUser(@Param("userId") String userId);
}

可以使用MapperFactoryBean,把接口加入到Spring中:

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"><property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" /><property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

注意:所指定的映射器类必须是一个接口,而不是具体的实现类。上面例子用的是注解,也可以用xml配置的形式。

一旦配置好,可以用相同的方式直接注入映射器到 business/service 对象中。MapperFactoryBean 处理 SqlSession 的创建和关闭它。如果使用 了 Spring 的事务,那么当事务完成时,session 将会提交或回滚。最终,任何异常都会被翻 译成 Spring 的 DataAccessException 异常。

最后调用Mybatis数据方法只需一行代码:

public class FooServiceImpl implements FooService {private UserMapper userMapper;public void setUserMapper(UserMapper userMapper) {this.userMapper = userMapper;
}public User doSomeBusinessStuff(String userId) {return this.userMapper.getUser(userId);
}

SqlSessionFactoryBean

要创建工厂 bean,放置下面的代码在 Spring 的 XML 配置文件中:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
</bean>

属性

SqlSessionFactory 有一个单独的必须属性— JDBC 的 DataSource。

一个通用的属性是 configLocation,它是用来指定 MyBatis 的 XML 配置文件路径的。 如果基本的 MyBatis 配置需要改变, 那么这就是一个需要配置文件的地方。

和spring结合的mybatis配置文件不需要一个完整的 MyBatis 配置。任意环境,数据源 和 MyBatis 的事务管理器都会被忽略。SqlSessionFactoryBean 会创建它自己的 sqlSessionFactory。

另一个需要配置文件的地方,是mybatis映射器xml文件和映射器类不在同一路径。有两个选择:第一是手动在 MyBatis 的 XML 配 置文件中使用部分来指定类路径。第二是使用工厂 bean 的 mapperLocations 属 性。

mapperLocations 属性使用一个资源位置的 list。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
</bean>

这会从类路径下加载在 sample.config.mappers 包和它的子包中所有的 映射器 文件。

从1.3.0后,configuration 属性加入。它规定不用xml配置文件直接插入configuration标签。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="configuration"><bean class="org.apache.ibatis.session.Configuration"><property name="mapUnderscoreToCamelCase" value="true"/></bean></property>
</bean>

事务

一个使用 MyBatis-Spring 的主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。MyBatis-Spring 利用了存在于 Spring 中的 DataSourceTransactionManager。

可以通过配置Spring的PlatformTransaction,来配置自己的事务。

在事务处理期间,一个单独的 SqlSession 对象将被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。

标准配置

开启Spring事务处理, 创建一个 DataSourceTransactionManager 对象。

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" />
</bean>

要注意, 为事务管理器指定的 DataSource 必须和用来创建 SqlSessionFactoryBean 的 是同一个数据源,否则事务管理器就无法工作了。

容器管理事务

如果你想让 Spring 参与到容器管理事务(CMT)中,那么 Spring 应该使用 JtaTransactionManager 或它的容 器指定的子类来配置

<tx:jta-transaction-manager />

如果你想使用CMT , 而不想使用Spring的事务管理。 必须配置SQLSessionFactory来使用MyBatis 的 ManagedTransactionFactory 。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="transactionFactory"><bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" /></property>  
</bean>

编程式事务管理

你 不 能 在 Spring 管 理 的 SqlSession 上 调 用 SqlSession.commit() , SqlSession.rollback() 或 SqlSession.close() 方 法 。 如 果 这 样 做 了 , 就 会 抛 出 UnsupportedOperationException 异常。注意在使用注入的映射器时不能访问那些方法。

如果你想编程式地控制事务,这段代码展示了使用 PlatformTransactionManager 来处理事务

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus status = txManager.getTransaction(def);
try {userMapper.insertUser(user);
}
catch (MyException ex) {txManager.rollback(status);throw ex;
}
txManager.commit(status);

使用SQLSession

在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession。一旦你获得一个 session 之后,你可以使用它来执行映射语句,提交或回滚连接,最后,当不再需要它的时 候, 你可以关闭 session。 使用 MyBatis-Spring 之后, 你不再需要直接使用 SqlSessionFactory 了,因为你的 bean 可以通过一个线程安全的 SqlSession 来注入,基于 Spring 的事务配置 来自动提交,回滚,关闭 session。

SqlSessionTemplate

SqlSessionTemplate 是 MyBatis-Spring 的核心。
这个类负责管理 MyBatis 的 SqlSession, 调用 MyBatis 的 SQL 方法, 翻译异常。 SqlSessionTemplate 是线程安全的, 可以被多个 DAO 所共享使用。它管理 session 的生命 周期,包含必要的关闭,提交或回滚操作。

SqlSessionTemplate 实现了 SqlSession 接口,在代码中无需对 MyBatis 的 SqlSession 替换。SqlSessionTemplate 通常是被用来替代默认的 MyBatis 实现的 DefaultSqlSession。

SqlSessionTemplate 对象可以使用 SqlSessionFactory 作为构造方法的参数来创建。

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><constructor-arg index="0" ref="sqlSessionFactory" />
</bean>

1、这个 bean 现在可以直接注入到 DAO bean 中。你需要在 bean 中添加一个 SqlSession 属性。

public class UserDaoImpl implements UserDao {private SqlSession sqlSession;public void setSqlSession(SqlSession sqlSession) {this.sqlSession = sqlSession;}public User getUser(String userId) {return (User) sqlSession.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);}
}

注入SqlSessionTemplate:

<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl"><property name="sqlSession" ref="sqlSession" />
</bean>

2、SqlSessionTemplate 有一个使用 ExecutorType 作为参数的构造方法。这允许你用来 创建对象。

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><constructor-arg index="0" ref="sqlSessionFactory" /><constructor-arg index="1" value="BATCH" />
</bean>

现在你所有语句都可以批量操作。

public void insertUsers(User[] users) {for (User user : users) {sqlSession.insert("org.mybatis.spring.sample.mapper.UserMapper.insertUser", user);}}

SqlSessionDaoSupport

SqlSessionDaoSupport 是 一 个 抽象 的支 持 类, 用来 为你 提供 SqlSession 。 调用getSqlSession()方法你会得到一个 SqlSessionTemplate,之后可以用于执行 SQL 方法。

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {public User getUser(String userId) {return (User) getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);}
}

通常 MapperFactoryBean 是这个类的首选,因为它不需要额外的代码。 但是,你要在dao中做其他事情,那么这个类就很有用。

SqlSessionDaoSupport 需要一个 sqlSessionFactory 或 sqlSessionTemplate 属性来 设 置 。

假设类 UserMapperImpl 是 SqlSessionDaoSupport 的子类,它可以在 Spring 中进行如 下的配置:

<bean id="userMapper" class="org.mybatis.spring.sample.mapper.UserDaoImpl"><property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

五 注入映射器

为了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 编写数据访问对象 (DAO)的代码,MyBatis-Spring 提供了一个动态代理的实现:MapperFactoryBean这个类 可以让你直接注入数据映射器接口到你的 service 层 bean 中。当使用映射器时,你仅仅如调 用你的 DAO 一样调用它们就可以了,但是你不需要编写任何 DAO 实现的代码,因为 MyBatis-Spring 将会为你创建代理。

使用注入的映射器代码,在 MyBatis,Spring 或 MyBatis-Spring 上面不会有直接的依赖。 MapperFactoryBean 创建的代理控制开放和关闭 session翻译任意的异常到 Spring 的 DataAccessException 异常中。此外,如果需要或参与到一个已经存在活动事务中,代理将 会开启一个新的 Spring 事务。

MapperFactoryBean

加入到Spring

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"><property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" /><property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

mapperInterface说明 MapperFactoryBean 创建的代理类实现了 UserMapper 接口,并且注入到应用程序中。

如果 XML 文件在类路径的 位置和映射器类相同时, 它会被 MapperFactoryBean 自动解析。不需要再mybatis的配置文件中指定映射器路径,除非在不同目录。

可以直接在 business/service 对象中以注入Spring bean 的方式直接注入映 射器:

<bean id="fooService" class="org.mybatis.spring.sample.mapper.FooServiceImpl"><property name="userMapper" ref="userMapper" />
</bean>

这个 bean 可以直接在应用程序逻辑中使用:

public class FooServiceImpl implements FooService {private UserMapper userMapper;public void setUserMapper(UserMapper userMapper) {this.userMapper = userMapper;}public User doSomeBusinessStuff(String userId) {return this.userMapper.getUser(userId);}
}

注意,上面没有Session的引用,打开或 关闭 session 的代码,MyBatis-Spring 会来关心它的。

MapperScannerConfigurer

没有必要在 Spring 的 XML 配置文件中注册所有的映射器。相反,你可以使用一个 MapperScannerConfigurer , 它 将 会 查 找 类 路 径 下 的 映 射 器 并 自 动 将 它 们 创 建 成 MapperFactoryBean。

创建 MapperScannerConfigurer

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="org.mybatis.spring.sample.mapper" />
</bean>

basePackage 属性是让你为映射器接口文件设置基本的包路径。 可以使用分号或逗号 作为分隔符设置多于一个的包路径。每个映射器将会在指定的包路径中递归地被搜索到。

注 意 , 没有必要去指定 SqlSessionFactory 或 SqlSessionTemplate , 因 为 MapperScannerConfigurer 将会创建 MapperFactoryBean,之后自动装配。但是,如果你使 用了一个 以上的 DataSource ,那 么自动 装配可 能会失效。 这种 情况下 ,你可 以使用 sqlSessionFactoryBeanName 或 sqlSessionTemplateBeanName 属性来设置正确的 bean 名 称来使用。

bean 的名称是必须的,而不是 bean 的引用,因 此,value 属性在这里替代通常的 ref:

<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />

六 使用Mybatis API

使用 MyBatis-Spring,你可以继续直接使用 MyBatis 的 API。仅仅在代码中使用 Spring 中 的 SqlSessionFactoryBean 来创建一个 SqlSessionFactory。

public class UserMapperSqlSessionImpl implements UserMapper {// SqlSessionFactory would normally be set by SqlSessionDaoSupportprivate SqlSessionFactory sqlSessionFactory;public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}public User getUser(String userId) {// note standard MyBatis API usage - opening and closing the session manuallySqlSession session = sqlSessionFactory.openSession();try {return (User) session.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);} finally {session.close();}}
}

小心使用此选项, 因为错误的使用会产生运行时错误, 或者更糟糕的数据一致性的问题。 这些是告诫:
1.它不会参与到 Spring 的事务之中。
2.如果 SqlSession 使用 DataSource,它也会被 Spring 事务管理器使用,而且当前 有事务在进行时,这段代码会抛出异常。
3.MyBatis 的 DefaultSqlSession 是线程不安全的。如果在 bean 中注入了它,就会 发生错误。
使用 DefaultSqlSession 创建的映射器也不是线程安全的。如果你将它们注入到 bean 中,是会发生错误的。
4.你必须保证在 finally 块中来关闭 SqlSession。

实例代码

https://github.com/mybatis/spring/tree/master/src/test/java/org/mybatis/spring/sample

Spring单元测试

https://blog.csdn.net/u013041642/article/details/71430293

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.zx.dao.UserDao;
import com.zx.domain.User;
import com.zx.mapper.UserMapper;/*** Example of MyBatis-Spring batch integration usage.*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:application-base.xml")
public class UserDaoTest{@Autowiredprotected UserDao userDao;@Autowiredprotected UserMapper userMapper;@Testpublic void testSelect() {User user = this.userMapper.selectOne(1);System.out.println(user);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330937.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在 eclipse 中 设置 jvm 的 运行时目录

然而 在 eclipse中 类所在包的目录是项目所在目录的 孙子目录 而不是 父目录&#xff1b;所以&#xff0c;如果要运行 诸如 chapter18.className这样的类 就需要 将 运行时目录设置为 项目目录/src 目录才行。

jvm系列(九):如何优化Java GC

转载自 jvm系列(九):如何优化Java GC「译」本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三篇《How to Tune Java Garbage Collection》,本文的作者是韩国人&#xff0c;写在JDK 1.8发布之前&#xff0c;虽然有些地方有些许过时&…

关闭json引用的方式

https://www.cnblogs.com/zjrodger/p/4630237.html 【具体方案】 1、如果你用的是FastJson&#xff0c;首先要关闭FastJson的“循环引用检测”特性。 2、如果你不想修改实体之间的关系&#xff0c;则将代码&#xff1a;“JSONField(serializefalse)”添加在下列方法中 public …

Redis学习记录

Redis简介 Redis是一个高性能的key-value非关系型数据库&#xff0c;可以存键&#xff08;key&#xff09;与5中不同类型的值&#xff08;value&#xff09;之间的映射&#xff08;mapping&#xff09;。 支持存储的value类型包括&#xff1a;String&#xff08;字符串&#…

jvm系列(十):教你如何成为Java的OOM Killer

转载自 jvm系列(十):教你如何成为Java的OOM Killer前言 虽然事隔半年&#xff0c;当时排查线上OOM事故的过程记忆犹新&#xff0c;每一个步骤都历历在目&#xff0c;感谢业务组、系统部、压测组、监控与应急部对架构组的强力支持&#xff0c;得以让这个Java内存问题水落石出&am…

java 程序的初始化顺序是怎样的?

【0】README 1&#xff09;本文 转自“ java 程序员面试笔试宝典”&#xff0c; 这个书有点意思&#xff1b; 【1】java程序初始化遵循三个原则&#xff08;rule&#xff09; r1&#xff09;静态变量 优先于 非静态变量&#xff1b; r2&#xff09;父类优先于子类进行初始化&a…

操作符

直接常量 double: 111d,111D 二进制&#xff1a;前缀为0b 十六进制&#xff1a;前缀为0x或0X&#xff0c;后面最大9位。 八进制&#xff1a;前缀为0&#xff0c;后面最大7位。 按位操作符 与&#xff08;&&#xff09;&#xff1a; 或&#xff08;||&#xff09;&#x…

jvm系列(十一):Java 8-从持久代到metaspace

转载自 jvm系列(十一):Java 8-从持久代到metaspaceJava 8介绍了一些新语言以及运行时新特点。其中一个特点便是完全移除了持久代(PermGen)&#xff0c;自从Oracle公司发布了JDK1.7后就已经宣布了这个决定。还有比如内部字符串&#xff0c;从JDK1.7开始就从持久代移除了&#xf…

我的控制反转,依赖注入和面向切面编程的理解

感谢http://blog.xiaohansong.com/2015/10/21/IoC-and-DI/ 的供图1.什么是控制&#xff1f; 如下图所示&#xff0c;我们看到了 软件系统中 对象的 高耦合现象。全体齿轮的转动由一个对象来控制&#xff0c;如类B。2.什么是 控制反转&#xff1f; 是用来对对象进行解耦。借助第…

在Spring Boot中使用切面统一处理自定义的异常

最近我们将项目的一个单独模块提取了一个微服务&#xff0c;这个微服务主要负责其他系统的接入。目的是发布主项目的时候不会影响到其他系统接入。在提取出的微服务中&#xff0c;需要定义一个正常返回的报文和异常返回的报文。正常返回报文就是正常业务返回的数据报文&#xf…

Java 8的新特性—终极版

转载自 Java 8的新特性—终极版 1. 简介 毫无疑问&#xff0c;Java 8是Java自Java 5&#xff08;发布于2004年&#xff09;之后的最重要的版本。这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。在本文中我们将学习这些新特性&#xff0c;并用实际的例子说明在…

ReviewForJob——java虚拟机的垃圾回收策略(个人总结)

理解jvm的垃圾回收策略&#xff0c;需要解决以下3个问题问题1&#xff1a;哪些内存需要回收&#xff1f;问题2&#xff1a;什么时候进行回收&#xff1f;问题3&#xff1a;怎样来回收&#xff1f;【解决问题1】哪些内存需要回收&#xff1f;jvm的内存区域有5大块&#xff1a;1&…

使用静态代理模式实现公用的报表导出功能

先聊一下什么是代理模式&#xff1f; 代理模式 给某个对象提供一个代理对象&#xff0c;并由代理独享控制对原对象的引用。什么意思呢&#xff1f;代理模式就有点像我们生活中常见的中介。 举个例子&#xff0c;我想买辆二手车&#xff0c;第一种方式是自己去找车源&#xff…

java前台线程(普通线程) 和 后台线程

【1】普通线程&#xff1a; 就是指 用户 创建的一般线程&#xff0c;具有个体性&#xff0c;不具有提供公共服务的性质&#xff0c;因此&#xff0c; 通常需要我们在 线程的 循环语句中 手动编写 循环结束语句&#xff0c;也即 线程运行终止的条件语句&#xff1b; 【2】后台线…

mysql中使用CASE WHEN

简单的使用CASE WHEN CASE SCORE WHEN A THEN 优 ELSE 不及格 END CASE SCORE WHEN B THEN 良 ELSE 不及格 END CASE SCORE WHEN C THEN 中 ELSE 不及格 END上面的sql等同于 CASE SCORE WHEN A THEN 优 WHEN B THEN 良 WHEN C THEN 中 ELSE 不及格 ENDTHEN后面的值与ELSE后面…

Java生成随机数的几种高级用法

转载自 进阶 | Java生成随机数的几种高级用法&#xff01;言归正传&#xff0c;众所周知&#xff0c;随机数是任何一种编程语言最基本的特征之一。而生成随机数的基本方式也是相同的&#xff1a;产生一个0到1之间的随机数。看似简单&#xff0c;但有时我们也会忽略了一些有趣的…

Java 可重入锁内存可见性分析

转载自 深度好文 | Java 可重入锁内存可见性分析一个习以为常的细节之前在做 ReentrantLock 相关的试验&#xff0c;试验本身很简单&#xff0c;和本文相关的简化版如下&#xff1a;&#xff08;提示&#xff1a;以下代码均可左右滑动&#xff09; private static ReentrantLoc…

java正则表达式 ^expr 和 [^expr] 和 ^[^expr]的比较

public class Main {private static String[] array {"Jav", "Java", "Hello"}; public static void main(String[] args) {String[] regexs {"^Java", // 以 Java开头的字符串"[^Java]",// 除了 J a v a 之外 的任何字符…

优秀 Java 程序员写代码的风格

转载自 涨姿势 | 优秀 Java 程序员写代码的风格今天突发奇想&#xff0c;对编码习惯和 编程风格 很感兴趣&#xff0c;于是乎&#xff0c;找了一下关于编程风格&#xff08;Java篇&#xff09;的资料&#xff0c;希望对爱好编码或者开始学习编码的同学有帮助&#xff01;来自《…

2017尼毕鲁笔试算法题

【1】题目&#xff1a; 给定一个无序数组&#xff0c;找到最长的单调自增子序列&#xff08;不一定连续&#xff0c;但是顺序不能乱&#xff09;的长度&#xff1b; 【2】看个荔枝&#xff1a;给定数组 [10, 9, 2, 5, 3, 7, 101, 18] 输出结果为 [2, 3, 7, 101]。。算法时间…