【Java】MyBatis与Spring框架整合(二)
本文讲解 Spring 注入映射器及事务功能的实现。
注入映射器实现
MyBatis 可以使用 SqlSession 的 getMapper ( Class<T> type ) 方法,根据指定的映射器和映射文件直接生成实现类。这样不必自行编写映射器的实现类,就可以调用映射器的方法进行功能实现。
SqlSessionTemplate 也有对应的 getMapper()方法,利用 MyBatis-Spring 提供的组件,可以不必每次调用 getMapper()方法,而是通过配置的方式直接为业务对象注入映射器实现。对于不包含其他非 MyBatis 的工作的数据访问操作,这是首选的做法。
使用 MapperScannerConfigurer 注入映射器
SQL 映射文件中须遵循以下命名原则:
1)映射的命名空间和映射器接口的名称相同。
2)映射元素的 id 和映射器接口的方法相同。
首先,有关 DAO 接口的实现类可以删除了。
配置注入映射器的代码如下:
<!-- 配置 DAO -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.xxxx.mapper" />
</bean>
basePackage 属性指定了扫描的基准包,MapperScannerConfigurer 将递归扫描基准包下所有接口。如果它们在 SQL 映射文件中定义过,则将它们动态注册为 MapperFactoryBean 。
注意:
1)basePackage 属性中可以包含多个包名。多个包名之间使用逗号或分号隔开。
2)MapperScannerConfigurer 创建的所有映射器实现都会被自动注入 SqlSessionFactory 实例。
3)若环境中配置了多个 SqlSessionFactory 实例,自动装载将无法进行。此时应显式指定所依赖的 SqlSessionFactory 实例。下面是示例
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<property name="basePackage" value="cn.bdqn.mapper" />
</bean>
映射器被注册到 Spring 的容器时,Spring 会根据其接口名称为其命名,默认规则是首字母小写的非完全限定类名。如 UserMapper 类型组件会被默认命名为 userMapper。
在业务逻辑实现类中使用 @Resource 或 @AutoWried 注解实现对业务组件的依赖注入。
Spring 配置文件中需要引入 context 命名空间,并添加一行配置代码
<!-- 配置扫描注解定义的业务 Bean -->
<context:component-scan base-package="cn.xxxx.service" />
声明式事务
首先了解一下事务相关的理论知识
原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
一致性(Consistency):事务在完成时,必须是所有的数据都保持一致状态。
隔离性(Isolation):并发事务执行之间无影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性。
持久性(Durability):一旦事务完成,数据库的改变必须是持久化的。
事务并发所可能存在的问题:
脏读:一个事务读到另一个事务未提交的更新数据。
不可重复读:一个事务两次读同一行数据,可是这两次读到的数据不一样。
幻读:一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据行。
丢失更新:撤消一个事务时,把其它事务已提交的更新的数据覆盖了。
JDBC定制了五种事务隔离级别处理事务并发:
TRANSACTION_NONE JDBC :驱动不支持事务
TRANSACTION_READ_UNCOMMITTED: 允许脏读、不可重复读和幻读。
TRANSACTION_READ_COMMITTED: 禁止脏读,但允许不可重复读和幻读。
TRANSACTION_REPEATABLE_READ: 禁止脏读和不可重复读,单运行幻读。
TRANSACTION_SERIALIZABLE: 禁止脏读、不可重复读和幻读。
隔离级别越高,意味着数据库事务并发执行性能越差,能处理的操作就越少。
JDBC规范虽然定义了事务的以上支持行为,但是各个JDBC驱动,数据库厂商对事务的支持程度可能各不相同。
出于性能的考虑我们一般设置 TRANSACTION_READ_COMMITTED。
通过Spring,我们无需处理获得连接、关闭连接、事务提交和回滚等这些操作,使得我们把更多的精力放在处理业务上。
事实上Spring并不直接管理事务,而是提供了多种事务管理器。它们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
本文主要讲解 Spring 提供的声明式事务处理机制,它基于 AOP 实现,无须编写任何事务管理代码,所有的工作全在配置文件中完成。
配置
需要用到 tx 和 aop 两个命名空间,所以首先要导入这两个命名空间
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<beans/>
配置一个事务管理器组件,这里使用 Spring 提供的事务管理器类 DataSourceTransactionManager
<!-- 定义事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
这里的 dataSource 是上文中配置的数据源组件。
可以通过 <tx :advice> 标签配置事务增强,设定事务的属性,为不同的业务方法指定具体的事务规则。
<!-- 为指定事务管理器设置事务属性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 定义属性,声明事务规则 -->
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"
read-only="false" />
<tx:method name="del*" propagation="REQUIRED" isolation="DEFAULT"
read-only="false" />
<tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT"
read-only="false" />
<tx:method name="query*" propagation="NEVER" read-only="true" />
<tx:method name="get*" propagation="NEVER" read-only="true" />
</tx:attributes>
</tx:advice>
transaction-manager 属性引用一个事务管理器 Bean
<tx:attributes> 子标签用来定制事务属性。事务属性通过 <tx:method> 标签进行设置。
<tx:method> 标签中 name 属性是必须的,用于指定匹配的方法,可以使用通配符( * )。其他属性均为可选,用于指定具体的事务规则。
Spring 事务的传播属性
名称 | 值 | 解释 |
---|---|---|
PROPAGATION_REQUIRED | 0 | 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是Spring默认的事务的传播。 |
PROPAGATION_SUPPORTS | 1 | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 2 | 支持当前事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 3 | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 4 | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 5 | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 6 | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 |
Spring 事务的隔离级别
名称 | 值 | 解释 |
---|---|---|
ISOLATION_DEFAULT | -1 | 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应 |
ISOLATION_READ_UNCOMMITTED | 1 | 这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻读。 |
ISOLATION_READ_COMMITTED | 2 | 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。 |
ISOLATION_REPEATABLE_READ | 4 | 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻读。 |
ISOLATION_SERIALIZABLE | 8 | 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻读。 |
最后是定义切面
<!-- 定义切面 -->
<aop:config>
<!-- 定义切入点 -->
<aop:pointcut expression="execution(* cn.xxxx.service..*.*(..))" id="pointcutTransaction" />
<!-- 将事务增强与切入点组合 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcutTransaction"/>
</aop:config>
使用注解实现声明式事务处理
Spring 支持使用注解配置声明式事务,所使用的注解是 @Transactional
首先需要在 Spring 配置文件中添加对注解配置的事务的支持
<tx:annotation-driven transaction-manager="transactionManager"/>
在 Service 业务逻辑实现类中添加注解
@Transactional
@Service("userSerivce")
public class UserService implements IUserService{ @Autowired
@Qualifier("userMapper")
private UserMapper userMapper; @Override
@Transactional(propagation=Propagation.SUPPORTS)
public List<USER> queryUsers() {
return userMapper.queryUsers();
}
}
注意:
1)在类上添加 @Transactional 注解可为该类的所有业务方法统一添加事务处理。如果某一业务方法需要采用不同的事务规则,可以在该业务方法上添加 @Transactional 注解单独进行设置。
2)不建议在查询方法上使用事务,会影响查询的性能。
使用注解配置事务时,所使用的属性与在 Spring 配置文件中使用的属性一致。
【Java】MyBatis与Spring框架整合(二)的更多相关文章
- 【Java】MyBatis与Spring框架整合(一)
本文将利用 Spring 对 MyBatis 进行整合,在对组件实现解耦的同时,还能使 MyBatis 框架的使用变得更加方便和简单. 整合思路 作为 Bean 容器,Spring 框架提供了 IoC ...
- 【mybatis源码学习】mybatis和spring框架整合,我们依赖的mapper的接口真相
转载至:https://www.cnblogs.com/jpfss/p/7799806.html Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注 ...
- 【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
一.动态SQL 什么是动态SQL,就是在不同的条件下,sql语句不相同的意思,曾经在“酒店会员管理系统”中写过大量的多条件查询,那是在SSH的环境中,所以只能在代码中进行判断,以下是其中一个多条件查询 ...
- Java基础-SSM之Spring和Mybatis以及Spring MVC整合案例
Java基础-SSM之Spring和Mybatis以及Spring MVC整合案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 能看到这篇文章的小伙伴,详细你已经有一定的Java ...
- 使用Spring框架整合Java Mail
我的博客名为黑客之谜,今天演示的案例中会出现我的邮箱,还不赶紧收藏!我现在是小白,但是随着时间的流逝,我会逐渐向大神走进,所以,喜欢我的,或者喜欢大神的,点一波关注吧!顺便说一下,双十二快到了,有什么 ...
- 由“单独搭建Mybatis”到“Mybatis与Spring的整合/集成”
在J2EE领域,Hibernate与Mybatis是大家常用的持久层框架,它们各有特点,在持久层框架中处于领导地位. 本文主要介绍Mybatis(对于较小型的系统,特别是报表较多的系统,个人偏向Myb ...
- mybatis 学习笔记(四):mybatis 和 spring 的整合
mybatis 学习笔记(四):mybatis 和 spring 的整合 尝试一下整合 mybatis 和 spring. 思路 spring通过单例方式管理SqlSessionFactory. sp ...
- Java EE互联网轻量级框架整合开发— SSM框架(中文版带书签)、原书代码
Java EE互联网轻量级框架整合开发 第1部分 入门和技术基础 第1章 认识SSM框架和Redis 2 1.1 Spring框架 2 1.2 MyBatis简介 6 1.3 Spring MVC简介 ...
- SSM :MyBatis与Spring的整合
MyBatis与Spring的整合 一:Spring整合MyBatis的准备工作: (1.)在项目中加入Spring,ByBatis及整合相关的jar文件 (2.)建立开发目录结构,创建实体类 (3. ...
随机推荐
- for循环输出数组中的分数
示例 var scores = [24, 32, 17]; // A数组 var arrayLength = scores.length;// 数组的长度 //当i<arrayLength时,可 ...
- 2017-2018-2 20155309 南皓芯 Exp3 免杀原理与实践
报告内容 2.1.基础问题回答 (1)杀软是如何检测出恶意代码的 ? 1:基于特征码 一段特征码就是一段或多段数据.(如果一个可执行文件(或其他运行的库.脚本等)包含这样的数据则被认为是恶意代码) 杀 ...
- 关于git中Pageant开机启动且自动关联秘钥
Pageant在git中主要负责和服务器端进行身份验证,但是我们每次在启动Pageant后都需要手动的加载秘钥文件,这其实是一个比较烦的过程,我们怎么能够使其自动的完成呢? 一.Pageant开机启动 ...
- C#编码、解码
1.HttpUtility.UrlEncode 方法: 对 URL 字符串进行编码,以便实现从 Web 服务器到客户端的可靠的 HTTP 传输.重载列表: [1]将字节数组转换为已编码的 URL 字符 ...
- Codeforces 442C Artem and Array (看题解)
Artem and Array 经过分析我们能发现, 如果对于一个a[ i ] <= a[ i + 1 ] && a[ i ] <= a[ i - 1 ]可以直接删掉. 最 ...
- Shell 错误输出重定向
转自:https://www.cnblogs.com/vijayfly/p/6234575.html shell将标准错误输出重定向到 其他地方 经常可以在一些脚本,尤其是在crontab调用时发现如 ...
- 064 UDF
一:UDF 1.自定义UDF 二:UDAF 2.UDAF 3.介绍AbstractGenericUDAFResolver 4.介绍GenericUDAFEvaluator 5.程序 package o ...
- 如何在MacBook的以太网端口上成功运行DHCP服务器?
我的目标是在我的MacBook以太网端口上安装一个以太网交换机,我将通过DHCP连接几个Raspberry Pi连接,每个都将运行VNC服务器进行远程访问,我希望我的互联网可以从我的MacBook的W ...
- C#并行编程(1):理解并行
什么是并行 并行是指两个或者多个事件在同一时刻发生. 在程序运行中,并行指多个CPU核心同时执行不同的任务:对于单核心CPU,严格来说是没有程序并行的.并行是为了提高任务执行效率,更快的获取结果. 与 ...
- 细说Vue作用域插槽,匹配应用场景。
最近在官方文档中看到,vue新增了一种插槽机制,叫做作用域插槽.要求的版本是2.1.0+. 首先来说一下:顾名思义,所谓作用域插槽,主要就在作用域,需要注意的是(以下几点看不懂不要紧,配合下面的例子, ...