spring与mybatis整合

mybatis-spring 官网
http://www.mybatis.org/spring/zh/index.html

方法1:点击下面的git链接到github下载
方法2:直接到maven仓库找对应的jar下载
http://mvnrepository.com/tags/maven
Spring-mybatis整合
1.步骤:
a加入Mybatis和Spring的有关jar
b 创建开发目录结构,创建实体类
c 创建数据访问接口
d 创建数据访问接口实现类
e 配置sql映射语句文件
f配置Mybatis应用配置文件
g配置spring应用配置文件

spring Ioc基本包
在这里插入图片描述

spring整合mybatis
在这里插入图片描述
apache的dbcp数据源
在这里插入图片描述
database-driver
在这里插入图片描述
spring Aop基本包
在这里插入图片描述
全部
在这里插入图片描述

  1. Spring核心配置文件applicationContext.xml
    1.1数据源的配置
    在这里插入图片描述
    1.2 SqlSessionFactoryBean为整合应用提供SqlSession对象资源
    在这里插入图片描述
    1.3 SqlSessionTemplate负责管理MyBatis的SqlSession,调用SQL映射语句,实现对数据库的访问
    在这里插入图片描述

Dao配置
在这里插入图片描述
1.4 MapperFactoryBean根据指定Mapper接口生成Bean实例
映射器对应的SQL映射文件与映射器的类路径相同,该映射文件可以自动被MapperFactoryBean解析
在这里插入图片描述
1.5 MapperScannerConfigurer根据指定包批量扫描Mapper接口并生成实例
MapperScannerConfigurer递归扫描基准包下所有接口,若它们在SQL映射文件中定义过,则动态注册为MapperFactoryBean,如此即可批量产生映射器实现类
在这里插入图片描述
开启扫描注解
在这里插入图片描述
扫描包路经

3.Spring事务
1.何为事务?
事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。就是把一系列的操作当成原子性去执行。
2.事务四个属性ACID
1、原子性(atomicity)
事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用
2、一致性(consistency)
一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中
例:用户A和用户B的前加起来一共是5000; 无论AB用户之间是如何相互转换的,事务结束后两个用户的钱加起来还是5000,这就是事务的一致性。
3、隔离性(isolation)
可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏
4、持久性(durability)
事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

隔离性:当多个线程都开启事务来操作数据库中的数据时,数据库系统要进行隔离操作,以保证各个线程获取数据的准确性。 不考虑事务的隔离性,会产生的几种问题:
01:脏读(未提交)
是指一个事务处理过程里读取了另一个未提交的事务中的数据,然后使用了这个数据;
例:a:100 , b给a转100。

02:不可重复读(一条记录update, 提交)
不可重复读是指在一个事务内,多次读取同一个数据,在这个事务还没有结束 ,另一个事务也访问该同一数据,但是由于第二个事务的修改,那么第一个事务两次读取的数据可能不一样,因此称为不可重复读;即同一个事务中原始数据读取不可重复。
例子:a:100, b:200
注:不可重复读和脏读的区别,脏读是某一个事务读取另一个事务未提交的脏数据;
不可重复读则是读取前一事务提交前的数据
03:幻读:(多条记录/一张表,update, 提交)

当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行修改,这种数据涉及到表中的全部数据行,同时,第二个事务也对这个表数据进行修改,这个修改是对表中新增/删除一条数据,那么操作第一个事务的用户发现表中的数据还没有修改的数据行,就好像发生了幻觉一样,这就是发生了幻读。
注:幻读和不可重复读都读取另一条已经提交的事务,所不同的是不可重复读查询的都是同一数据项,而幻读针对的是一批数据整体。

数据库提供的四种隔离级别:
01:Read uncommitted(读未提交):最低级别,任何情况都会发生。
02:Read Committed(读已提交):可避免脏读的发生。
03:Repeatable read(可重复读):可避免脏读、不可重复读的发生。
04:Serializable(串行化):避免脏读、不可重复读,幻读的发生。

注: 四种隔离级别最高:Seralizable级别,最低的是Read uncommitted级别; 级别越高,执行效率就越低; 隔离级别的设置只对当前链接有效,对JDBC操作数据库来说,一个Connection对象相当于一个链接,只对该Connection对象设置的隔离级别只对该connection对象有效,与其它链接connection对象无关。
01:Mysql的默认隔离级别是:可重复读:Repeatable read;
02:oracle数据库中,只支持seralizable(串行化)级别和Read committed();默认的是Read committed级别;

3.Spring中的事务管理
Spring支持编程式事务管理和声明式的事务管理。
3.1编程式事务管理
将事务管理代码嵌到业务方法中来控制事务的提交和回滚
缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

3.2声明式事务管理
一般情况下比编程式事务好用。将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。
a.xml配置声明式事务

<!-- 1. 配置事务管理器 -->
	<bean 
id="transactionManager" 		
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 2. 配置事务属性 -->
	<!--<tx:advice>元素声明事务通知-->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!-- 根据方法名指定事务的属性 -->
			<tx:method name="*"/>
			<!--propagation配置事务传播行为-->
			<tx:method name="purchase" propagation="REQUIRES_NEW"/>
			<!--isolation配置事务的隔离级别-->
			<tx:method name="update*" isolation="SERIALIZABLE"/>
			<!--rollback-for配置事务遇到异常必须回滚,no-rollback-for配置事务遇到异常必须不能回滚-->
			<tx:method name="add*" 
rollback-for="java.io.IOException" 			
no-rollback-for="com.dmsd.spring.tx.BookStockException"/>
			<!--read-only配置事务只读属性-->
			<tx:method name="find*" read-only="true"/>
			<!--timeout配置事务的超时属性-->
			<tx:method name="get*" timeout="3"/>
		</tx:attributes>
	</tx:advice>
	
<!-- 3. 配置事务切入点, 以及把事务切入点和事务属性关联起来 -->
<aop:config>
	<aop:pointcut expression="execution(* com.atguigu.spring.tx.xml.service.*.*(..))" 
		id="txPointCut"/>
	<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>	
</aop:config>

4.spring管理事务属性
4.1传播行为
事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如方法可能继续在现有事务中运行,也可能开启一个新的事务,并在自己的事务运行。spring中的事务传播行为可以由传播属性指定。spring指定了7种类传播行为。

REQUIRED 如果有事务在运行,当前的方法就在这个事务内运行,否则就开启一个新的事务,并在自己的事务内 运行,默认传播行为
REQUIRED_NEW 当前方法必须启动新事务,并在自己的事务内运行,如果有事务正在运行,则将它挂起
SUPPORTS 如果有事务在运行,当前的方法就在这个事务内运行,否则可以不运行在事务中
NOT_SUPPORTED 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务
将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
MANDATORY 当前的方法必须运行在事务内部,如果没有正在运行的事务,就会抛出异常
NEVER 当前方法不应该运行在事务中,如果有运行的事务,就抛出异常
NESTED 如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行。嵌套的事务

4.2事务隔离级别
并发事务会导致发生以下三种类型的问题
脏读 发生在一个事务读取了另一个事务改写尚未提交的数据时,改写的数据被回滚 了,那么第一个事务获取的数据无效
不可重复读 当同一个事务执行两次及以上相同的查询时,每次都得到不同的数据。一般因 为另一并发事务在两次查询期间进行了更新
幻读 第一个事务读取了一些数据,此时第二个事务在该表中插入了一些新数据,这 是第一个事务再读取相同的数据就会多几行

DEFAULT 使用底层数据库的默认隔离级别,大部分数据库,默认隔离级别都是 READ_COMMITED
READ_COMMITED 只允许事务读取已经被其他事务提交的更改,可以避免脏读,但不可 重复读和幻读问题仍然可能出现
READ_UNCOMMITED 允许事务读取未被其他事务提交的更改。脏读,不可重复读,幻读都 可能会出现
REPEATABLE_READ 确保事务可以多次从一个字段中读取相同的值。在这个事务持续期 间,禁止其他事务对这个字段进行更新,可以避免脏读和不可重复读, 但是幻读的问题依然存在
SERIALIZABLE 确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止 其他事务对该表执行插入,更新,删除。所有的并发问题都能避免, 但是性能比较低。
注意:事务的隔离级别需要底层数据库引擎的支持,而不是应用程序或者框架的支持
Oracle支持2种事务隔离级别:READ_COMMITED,SERIALIZABLE
MySQL支持4种事务隔离级别
4.3回滚规则
默认情况下只有未检查异常(RuntimeException和Error类型的异常)会导致事务回滚。事务的回滚规则可以通过属性管理
rollbackFor:遇到时必须进行回滚
noRollbackFor:一组异常类,遇到时必须不能回滚
<tx:method name=“add*”
rollback-for=“java.io.IOException”
no-rollback-for=“com.dmsd.spring.tx.BookStockException”/>
4.4只读属性
如果事务只读数据但不修改可以通过配置只读事务属性,帮助数据库引擎优化事务。只读事务属性:表示这个事务只读读取数据,但是不更新数据
4.5超时事务属性
事务可以在行和表上获得锁,因此长事务会占用资源,并对整体性能产生影响。可以配置超时事务属性,事务在强制回滚之前可以保持多久,这样可以避免长期运行的事务占用资源

5.用 @Transactional 注解声明式管理事务

<!-- 1.配置事务管理器 -->
<bean id="transactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2.启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

注意:添加xmlns命名空间xmlns:tx和xmlns:aop

<beans 
	xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
   		http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd 
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>

3.使用@Transactional为方法添加事务支持

<!-- 开启事务注解 -->
	<tx:annotation-driven transaction-manager="txManager"/>
	
	<!-- 1.事务管理器 -->
	<bean id="txManager"  
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource" />
	</bean>

@Transactional
@Service("userService")
public class UserServiceImpl implements UserService {

	@Resource
	private UserMapper userMapper;

	public User getUserById(int id) {
		return userMapper.getUserById(id);
	}

	@Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.DEFAULT)
	@Override
	public int addUser(User user) {
		int count = userMapper.addUser(user);
		int a = 10/0;
		return count;
	}
}

6.Spring 表达式语言(Spring Expression Language)
public * addNewUser(entity.User): “*”表示匹配所有类型的返回值。
public void (entity.User): “”表示匹配所有方法名。
public void addNewUser(…): “…”表示匹配所有参数个数和类型。

  • com.service..(…):匹配com.service包下所有类的所有方法。
  • com.service….(…):匹配com.service包及其子包下所有类的所有方法

扩充:Spring的文档,在事务那一章有明确的解释:
**“只读事务”**并不是一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。

但是你非要在“只读事务”里面修改数据,也并非不可以,只不过对于数据一致性的保护不像“读写事务”那样保险而已。
因此,“只读事务”仅仅是一个性能优化的推荐配置而已,并非强制你要这样做不可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值