Spring中的事务管理实例详解
spring事务管理
易可导航
示例代码:
UserManagerImpl类代码:
public void addUser(User user) { Session session = null; try { //session = HibernateUtils.getSession(); session = HibernateUtils.getSessionFactory().getCurrentSession(); session.beginTransaction(); session.save(user); //保存日志 Log log = new Log(); log.setType("安全日志"); log.setDetail("xxx进入系统"); log.setDate(new Date()); LogManagerImpl logManager = new LogManagerImpl(); logManager.addLog(log); session.getTransaction().commit(); } catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }
2023/10/23
易可导航
getCurrentSession()与openSession()的区别
❖ 采用getCurrentSession()创建的session会绑定到当前 线程中,而采用openSession()创建的session则不会。
❖ 采用getCurrentSession()创建的session在commit或 rollback时会ห้องสมุดไป่ตู้动关闭,而采用openSession()创建的 session必须手动关闭
Spring核心系列之Spring中的事务
Spring核⼼系列之Spring中的事务Spring核⼼系列之Spring中的事Spring核⼼系列之Spring中的事务Hello,⼤家好,前⾯两篇⽂章给⼤家分享了Spring AOP,今天就趁热打铁,给⼤家分享⼀下,Spring中的事务,事务这个事,其实在国内⼀些⼩公司,⼀般都会忽略的,尤其是很多⽹站,设计不到钱的系统,不会在乎这个东西,事务不回滚造成的结果⽆⾮就是脏数据,脏改等后果。
因为作者以前待过的⼀个房产⽹站,根本就不在乎这个事务,有问题就有问题了,反正⽤户也没充钱在⽹站上。
呵呵。
今天还是和⼤家分享⼀下这个Spring的事务,因为这个东西算是Spring 内部使⽤AOP最好的⼀个体现,体现了AOP思想,OK,⽂章结构:Spring boot 中的事务Spring事务中的事务属性1. Spring boot 中的事务看到Spring boot,很多⼈肯定感觉是被忽悠了,为什么说讲Spring事务,这⼜来Spring boot搞事情。
⽤过Spring boot的⼩伙伴其实都知道,这两个没什么⼤的区别,笔者这⾥使⽤Spring boot来演⽰,完全是为什么了简便。
因为搭⼀个Spring传统的ssm三件套⼯程可能要花费5分钟,⽽搭建⼀个Spring boot的"ssm"⼯程,就是⿏标点⼀点的事。
⽽且开启事务也是⼀个注解的事。
所以,⽼铁们,对不住了,这⼀篇⽤Spring boot和⼤家演⽰Spring的事务,这⾥我给⼀个传送门,是传统项⽬的事务,⼤家可以参考下:传统Spring⼯程的Spring事务废话不多说,直接上Spring boot代码:.@EnableTransactionManagement 表⽰开启事务!.这是⼀个Service,内部的personMapper是⼀个dao接⼝,持久化⽤的mybatis.演⽰的效果应该是:当调⽤PersonService的testTx()时,由于开启了事务,所以update2报异常时,应该会回滚。
Spring事务管理(详解+实例)
1 初步理解理解事务之前,先讲一个你日常生活中最常干的事:取钱。
比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱;然后ATM出1000元钱。
这两个步骤必须是要么都执行要么都不执行。
如果银行卡扣除了1000块但是ATM出钱失败的话,你将会损失1000元;如果银行卡扣钱失败但是ATM却出了1000块,那么银行将损失1000元。
所以,如果一个步骤成功另一个步骤失败对双方都不是好事,如果不管哪一个步骤失败了以后,整个取钱过程都能回滚,也就是完全取消所有操作的话,这对双方都是极好的。
事务就是用来解决类似问题的。
事务是一系列的动作,它们综合在一起才是一个完整的工作单元,这些动作必须全部完成,如果有一个失败的话,那么事务就会回滚到最开始的状态,仿佛什么都没发生过一样。
在企业级应用程序开发中,事务管理必不可少的技术,用来确保数据的完整性和一致性。
事务有四个特性:ACID∙原子性(Atomicity):事务是一个原子操作,由一系列动作组成。
事务的原子性确保动作要么全部完成,要么完全不起作用。
∙一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。
在现实中的数据不应该被破坏。
∙隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
∙持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。
通常情况下,事务的结果被写到持久化存储器中。
2 核心接口Spring事务管理的实现有许多细节,如果对整个接口框架有个大体了解会非常有利于我们理解事务,下面通过讲解Spring的事务接口来了解Spring实现事务的具体策略。
Spring事务管理涉及的接口的联系如下:2.1 事务管理器Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
Spring事务管理案例
Spring事务管理案例事务管理简介 Spring 事务管理有两种⽅式:⼀种是编程式事务管理,即通过编写代码实现事物管理,包括定义事务的开始,程序正常执⾏后的事物提交,异常时进⾏的事务回滚。
另⼀种是基于AOP技术实现的声明式事务管理,其主要思想是将事务管理作为⼀个“切⾯”代码单独编写,我们只⽤关⼼核⼼业务逻辑代码,然后通过AOP技术将事务管理的“切⾯”代码织⼊到业务类中,声明式事务管理有包括基于AOP⽅式的事务管理和基于 @Transactional注解⽅式的事务管理,声明式事务管理极⼤的简化了编程式事务管理的操作流程,不再需要重复地执⾏定义事物的开始,程序正常执⾏后事务提交,异常时进⾏事物回滚这些繁琐的操作,⽽基于 @Transactional注解的声明式事务⼜进⼀步简化了基于AOP的事务管理,减少了Spring配置代码。
声明式事务的缺点在于**只能作⽤到⽅法级别**,⽆法做到像编程式事务那样能控制到代码块级别。
事务传播⾏为 事务规则也就是事务传播⾏为,⽤于解决业务层⽅法之间的相互调⽤的问题题。
常见的事物传播⾏为可分为以下⼏种:名称说明REQUIRED表⽰当前⽅法必须运⾏在⼀个事物环境中,如果⼀个现有的事物正在运⾏,该⽅法将运⾏在这个事务中,否则,就要开始⼀个新的事务REQUIRESNEW表⽰当前⽅法必须运⾏在⾃⼰的事务⾥SUPPORTS表⽰当前⽅法不需要事务处理环境,但如果有⼀个事务正在运⾏的话,则这个⽅法也可以运⾏在这个事务中MANDATORY表⽰当前⽅法必须运⾏在⼀个事务上下⽂中,否则就抛出异常NEVER表⽰当前⽅法不应该运⾏在⼀个事务上下⽂中,否则就抛出异常 事务管理的主要任务是事务的创建,事务的回滚和事务的提交,是否需要创建事务及如何创建事务,是由事务传播⾏为控制的,通常数据的读取可以不需要事务管理,或者可以指定为只读事务,⽽对于数据的增加,删除和修改操作,则有必要进⾏事务管理。
如果没有指定事务的传播⾏为,Spring默认采⽤REQUIRED。
(转)Spring的编程式事务例子
(转)Spring的编程式事务例⼦纯JDBC操作, 对某些项⽬来说, 也许更好, Spring JDBC Framework让你不⽤关⼼Connection, Statement, ResultSet.定义数据源spring事务编程的例⼦<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">spring事务编程的例⼦<property name="jndiName">spring事务编程的例⼦<value>java:/comp/env/jdbc/oracle</value>spring事务编程的例⼦</property>spring事务编程的例⼦</bean>定义事务管理器<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean>定义daospring事务编程的例⼦<bean id="customerDAO" class="com.waterye.dao.impl.CustomerDAOImpl">spring事务编程的例⼦<property name="dataSource" ref="dataSource"/>spring事务编程的例⼦<property name="transactionManager" ref="transactionManager"/>spring事务编程的例⼦</bean>public class CustomerDaoImpl extends JdbcDaoSupport implements CustomerDAO {private DataSource dataSource;pirvate TransactionManager transactionManager;public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}public void setTransactionManager(DataSourceTransactionManager transactionManager) {this.transactionManager = transactionManager;}public Map get(Integer id) throws Exception {String querySql = "select * from customer where id = ?";return getJdbcTemplate().queryForMap(querySql, new Object[] { id });}public void insert(final Map customer) throws Exception {String seqSql = "select customer_seql.nextval from dual";String insertSql = "insert into customer (id, code, name, status) values (?, ?, ?, ?)";TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);transactionTemplate.execute(new TransactionCallbackWithoutResult() {protected void doInTransactionWithoutResult(TransactionStatus status) {JdbcTemplate jdbcTemplate = getJdbcTemplate();int id = jdbcTemplate.queryForInt(seqSql);Object[] params = new Object[] { new Integer(id), customer.get("code"), customer.get("name"), map.get("status") }; jdbcTemplate.update(insertSql, params);}}}public void update(final Map customer) throws Exception {//}public void delete(Integer id) throws Exception {String deleteSql = "delete from customer where id = ?";TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);transactionTemplate.execute(new TransactionCallbackWithoutResult() {protected void doInTransactionWithoutResult(TransactionStatus status) {getJdbcTemplate().update(deleteSql, new Object[] { id });}}}public List findValidCustomers() throws Exception {String querySql = "select * from customer where status = 'valid' order by code";return getJdbcTemplate().query(querySql, new OracleColumnMapRowMapper());}}。
enabletransactionmanagement用法
enabletransactionmanagement用法enableTransactionManagement是一个方法,用于在一个应用程序中启用事务管理。
它通常用于配置一个事务管理器,以便应用程序可以开始使用事务来管理数据库操作或其他资源的访问。
该方法的使用方式可能会因不同的框架或平台而有所不同。
以下是一个典型的例子,用于在Spring框架中启用事务管理:1. 首先,在应用程序的配置文件(通常是一个XML文件,如applicationContext.xml)中添加以下代码,以启用事务管理器:<tx:annotation-driven/>2. 在需要启用事务管理的类或方法上添加@Transactional注解,示例如下:
@Transactionalpublic void performDatabaseOperation() { 在此方法中执行数据库操作}此时,当performDatabaseOperation方法被调用时,事务管理器会自动为该方法开启一个事务,如果该方法成功执行,则事务会被提交,否则会被回滚。
需要注意的是,具体的用法会根据具体的框架和平台而有所不同。
在使用enableTransactionManagement方法时,建议查阅相关框架或平台的文档,以了解更详细的用法和配置方式。
SpringBoot事务注解详解
SpringBoot事务注解详解SpringBoot事务注解详解@Transactionalspring 事务注解1.简单开启事务管理@EnableTransactionManagement // 启注解事务管理,等同于xml配置⽅式的 <tx:annotation-driven />2.事务注解详解默认遇到throw new RuntimeException(“…”);会回滚需要捕获的throw new Exception(“…”);不会回滚指定回滚@Transactional(rollbackFor=Exception.class)public void methodName() {// 不会回滚throw new Exception("...");}指定不回滚@Transactional(noRollbackFor=Exception.class)public ItimDaoImpl getItemDaoImpl() {// 会回滚throw new RuntimeException("注释");}如果有事务,那么加⼊事务,没有的话新建⼀个(不写的情况下)@Transactional(propagation=Propagation.REQUIRED)容器不为这个⽅法开启事务@Transactional(propagation=Propagation.NOT_SUPPORTED)readOnly=true只读,不能更新,删除@Transactional (propagation = Propagation.REQUIRED,readOnly=true)设置超时时间@Transactional (propagation = Propagation.REQUIRED,timeout=30)设置数据库隔离级别@Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)3.指定事务管理器spring Boot 使⽤事务⾮常简单,⾸先使⽤注解 @EnableTransactionManagement 开启事务⽀持后,然后在访问数据库的Service⽅法上添加注解 @Transactional 便可。
spring事务配置详解及分析
Spring事务配置的五种方法及分析总结如下:Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
具体如下图:根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:第一种方式:每个Bean都有一个代理<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-2.5.xsd/schema/context/schema/context/spring-context-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd"><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"><property name="configLocation" value="classpath:hibernate.cfg.xml"/><property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/> </bean><!-- 定义事务管理器(声明式的事务)抽象的方法作为框架类比如原始接口---->抽象类实现这个接口------>具体的业务类那么这个抽象类就是框架类了,封装了一些具体业务类通用的框架了例子:AbstractPlatformTransactionManager->HibernateTransactionManager->PlatformTransactionManager --><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"/></bean><!-- 配置DAO --><bean id="userDaoTarget" class="erDaoImpl"><property name="sessionFactory" ref="sessionFactory"/></bean><bean id="userDao"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!-- 配置事务管理器 --><property name="transactionManager" ref="transactionManager"/><property name="target" ref="userDaoTarget"/><property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao"/><!-- 配置事务属性 --><!-- 这个方式会映射成Properties --><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop></props></property><!—TransactionAttributeSource主要是处理哪个方法需要事务,以及事务是什么级别的,transactionAttributeSource 是类的实例transactionAttributes是transactionAttributeSource需要处理的属性transactionAttributeSource 会根据TransactionAttribute 属性类和对应的class method生成TransactionAttribute类这两个属性说明在TransactionProxyFactoryBean 上有setTransactionAttributeSource()与setTransactionAttributes()方法,它们是用来设定交易属性的策略实例。
spring事务详解(基于注解和声明的两种实现方式)
spring事务详解(基于注解和声明的两种实现⽅式)Spring事务( Transaction )事务的概念事务是⼀些sql语句的集合,作为⼀个整体执⾏,⼀起成功或者⼀起失败。
使⽤事务的时机⼀个操作需要多天sql语句⼀起完成才能成功程序中事务在哪⾥说明加在业务类的⽅法上⾯(public⽅法上⾯),表⽰业务⽅法执⾏时,需要事务的⽀持。
不同的事务管理器不同的数据库访问技术,处理事务是不同的1. 使⽤jdbc访问数据库,事务处理public void updateAccount(){Connection con = .....;con.setAutoCommit(false);state.insert();state.update();mit();con.setAutoCommit(true);}2. MyBatis执⾏数据库,处理事务public void updateAccount(){SqlSession sqlSession = SqlSessionFactory.openSession(false);try{sqlSession.insert(...);sqlSession.update(...);mit();}catch(Exception e){sqlSession.rollback();}}spring统⼀管理事务,把不同的数据库访问技术的事务处理统⼀起来使⽤spring的事务管理器,管理不同数据库访问技术的事务处理。
开发⼈员只需要掌握spring的事务处理⼀个⽅案,就可以实现使⽤不同数据库访问技术的事务管理。
尽管事务⾯向的是spring,有spring管理事务,做事务提交和回滚。
spring事务管理器spring框架使⽤事务管理器对象,管理所有的事务。
事务管理器接⼝: PlatFormTransactionManager作⽤:定义了事务的操作,主要是commit() , rollback()事务管理器有很多的实现类:⼀种数据库访问计数有⼀个实现类。
通过实例跟我学Spring从入门到精通——在Spring框架中实现编程式的事务管理的应用实例(Eclipse版本第2部分
return true;
}
(3)完整的程序代码如下
package com.px1987.springwebapp.dao;
import erInfoVO;
import org.springframework.jdbc.core.*;
import java.util.*;
String updateSQL2 = "update userInfo2 set userPassWord = ? where userName
=? and userPassWord=?";
this.jdbcTemplate.update(updateSQL1,parameter);
this.jdbcTemplate.update(updateSQL2,parameter);
如果沒有发生错误,
则最后我们使用 commit()来提交操作。
*/
}
catch (DataAccessException ex)
{
transactionManager.rollback(status); // 也 可 以 执 行
tus.setRollbackOnly();
throw ex;
}
mit(status);
=? and userPassWord=?";
String updateSQL2 = "update abcTable set userPassWord = ? where userName
=? and userPassWord=?";
DefaultTransactionDefinition def = new DefaultTransactionDefinition(); TransactionStatus status = transactionManager.getTransaction(def); try {
Spring实现事务的三种方式
Spring实现事务的三种⽅式事务:保证数据的运⾏不会说A给B钱,A钱给了B却没收到。
实现事务的三种⽅式(重要代码):1.aspectJ AOP实现事务:<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dateSource"></property></bean><tx:advice id="stockAdvice" transaction-manager="dataSourceTransactionManager"><tx:attributes><tx:method name="by*" isolation="DEFAULT" propagation="REQUIRED" rollback-for="MyExepction"/><tx:method name="select*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"></tx:method></tx:attributes></tx:advice><aop:config><aop:pointcut id="exAdvice" expression="execution(* *..service.*.*(..))"></aop:pointcut><aop:advisor advice-ref="stockAdvice" pointcut-ref="exAdvice"></aop:advisor></aop:config>2.事务代理⼯⼚Bean实现事务:<bean id="tproxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><property name="transactionManager" ref="dataSourceTransactionManager"></property><!–写的是事务–> <property name="target" ref="byStockService"></property><!–要进⾏事务的类–><property name="transactionAttributes"><props><!–key写的是service层要增强的⽅法–><!– 事务的隔离级别,后⾯逗号后⾯是异常类,⽤于回滚数据–><prop key="ByStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-MyExepction</prop></props></property></bean>3.注解⽅式实现事务:<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>在需要进⾏事务的⽅法上增加⼀个注解“@Transactional(rollbackFor = MyExepction.class )”做⼀个买股票的⼩例⼦来看⼀下事务:1.使⽤事务⼯⼚Bean:xml:这个异常刚好卡在⽀付⾦额,和股票增加直接,RuntimeException是运⾏时异常Exception是检查异常两者的区别:运⾏时异常是默认回滚,检查异常是默认提交的。
spring事务管理
5事务管理为了描述事务的概念,我们拿买电影票来举例。
买一张电影票通常有一下步骤:检查剩余座位的数量,确定是否能给你提供你需要的座位个数每卖出一张票,可用座位的数量就应该减一付款售票员把票给你如果一切顺利的话,你就可以欣赏到一场一鸣惊人的电影,而影院也增加了收入。
但是如果有环节出差错了怎么办呢?比如说:你用来付款的信用卡没钱了?显然,你不会拿到票,影院也拿不到钱。
但是如果说座位的数量在下个人购买之前没有被恢复到原来的状态,那么电影也许因为人为原因而不会满场了。
或者如果出现这样的情况:一切都很顺利,但是发放票的时候出了问题。
你只好乖乖的呆在家里看电视了,而且还损失了一小笔钱。
为了保证剧院和你都不受到损失,上面的操作应该用事务封装起来。
作为事务,它应该被看成是一个单独的动作,以保证要么所有的操作都成功,或者所有的操作都回滚到初始的状态。
在软件中,事务有着举足轻重的地位,确保数据和资源保持一致的状态。
如果没有事务,那么数据有可能因为应用程序的业务逻辑而变成脏数据,或者变成与其他数据不统一的数据。
让我们快速浏览一下事务向导和他是如何工作的。
有以下四个因素。
5.1.1 用四句话来解释事务在软件开发的一个重要传统里,可以用一个单词首字母的缩写来描述一个事务:ACID,简言之,ACID代表Atomic(原子性)事务由一个或多个动作绑定起来作为一个单独的工作单元。
原子性保证事务中所有的操作要么都执行,或者都不执行。
如果所有的动作都执行了,那么事务就是成功的,如果其中有一个动作失败了,那么整个事务都失败,而且要执行回滚操作。
Consistent(一致性)一旦事务结束(可能成功了也可能失败了),那么系统所模拟的业务逻辑要处于一致的状态。
数据不应该被实体关系破坏。
Isolated(隔离性)事务应该允许多个用户操作一个数据,一个用户的操作应该不受另一个用户操作的影响。
因此事务之间应该是相互隔离的,以阻止他们在操作中同时读写同一数据。
Spring使用注解对事务控制详解与实例
Spring使⽤注解对事务控制详解与实例1.什么是事务⼀荣俱荣,⼀损俱损,很多复杂的操作我们可以把它看成是⼀个整体,要么同时成功,要么同时失败。
事务的四个特征ACID:原⼦性(Atomic):表⽰组成⼀个事务的多个数据库的操作的不可分割的单元,只有所有的操作成功才算成功,整个事务提交,其中任何⼀个操作失败了都是导致整个所有操作失败,事务会回滚。
⼀致性(Consistentcy):事务操作成功后,数据库所处的状态和业务规则⼀致。
如果A账户给B账户汇100,A账户减去100,B加上100,两个账户的总额是不变的。
隔离性(islation):在多个数据库的操作相同的数据并发时,不同的事务有⾃⼰的数据空间,事务与事务之间不受⼲扰(不是绝对的)。
⼲扰程度受数据库或者操作事务的隔离级别来决定,隔离级别越⾼,⼲扰就越低,数据的⼀致性越好,并发性就越差。
持久性(Druability):⼀旦事务提交成功,数据就被持久化到数据库,不可以回滚。
2.spring使⽤注解对事务的控制 Spring 事务管理有两种⽅式:编程式事务管理、声明式事务管理 编程式事务管理通过TransactionTemplate⼿动管理事务,在实际应⽤中很少使⽤,我们来重点学习声明式事务管理 声明式事务管理有三种实现⽅式:基于TransactionProxyFactoryBean的⽅式、基于AspectJ的XML⽅式、基于注解的⽅式 1. 新建⼀个java⼯程——导⼊spring 和事务管理所需要的jar ——然后选择全部jar 右键Build path ——最后如图(我的java版本jre是1.8)2.在src⽬录下新建5个包如图 dao :数据连接层,主要⽤于存放对数据进⾏操作的类 model:模型层,主要⽤于存放实体类 service:服务层,主要⽤于对数据连接层进⾏操作的⼀些服务类。
util:⼯具类,主要⽤于存储⼯具⽅法 test:⽤于测试类3.在dao数据连接层,建⽴⾥与数据库操作的类与对应的接⼝(Order 订单,detail订单明细) 3.1 定义detailDao接⼝ 代码如下:1package com.spring.dao;23import com.spring.model.Detail;4import com.spring.model.Order;56public interface detailDao {7//保存订单明细8public void saveDetail(Detail detail);9101112 } 3.2 定义OrderDao接⼝代码如下:1package com.spring.dao;23import com.spring.model.Order;45public interface OrderDao {6//保存订单7public void saveOrder(Order order);891011 } 3.3 实现以上接⼝detailDaoImp 代码如下:1package com.spring.dao;23import javax.sql.DataSource;45import org.springframework.jdbc.core.JdbcTemplate;67import com.spring.model.Detail;8import com.spring.model.Order;910public class detailDaoImp implements detailDao {1112private DataSource dataSource;13private JdbcTemplate jdbcTemplate;1415public void setDataSource(DataSource dataSource) {16this.dataSource = dataSource;17this.jdbcTemplate = new JdbcTemplate(dataSource);18 }19//保存订单明细20public void saveDetail(Detail detail) {21 String SQL = "insert into t_detail values(null,?,?,?))";22 jdbcTemplate.update(SQL, new Object[] { detail.getItemName(),detail.getQuantity(),detail.getOrderId() });23 System.out.println("Insert detail success!");24 }2526 }OrderDaoImp代码如下:package com.spring.dao;import javax.sql.DataSource;import org.springframework.jdbc.core.JdbcTemplate;import com.spring.model.Order;public class OrderDaoImp implements OrderDao {private DataSource dataSource;private JdbcTemplate jdbcTemplate;public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;this.jdbcTemplate = new JdbcTemplate(dataSource);}//插⼊订单public void saveOrder(Order order) {String SQL = "insert into t_order values (null,?)";System.out.println(SQL);System.out.println(order.getTotal_price());jdbcTemplate.update(SQL, new Object[]{order.getTotal_price()});System.out.println("Insert order success!");}}4.在model层中新建两个实体类 (Order订单类,detail订单明细类) Order订单类代码如下:1package com.spring.model;23/*4 * 订单表5*/6public class Order {7//订单编号8private Integer order_id;9//订单总⾦额10private Integer total_price;11public Integer getOrder_id() {12return order_id;13 }14public void setOrder_id(Integer order_id) {15this.order_id = order_id;16 }17public Integer getTotal_price() {18return total_price;19 }20public void setTotal_price(Integer total_price) {21this.total_price = total_price;22 }23 } detail订单明细类代码如下:1package com.spring.model;23/**4 * 商品明细表5 * @author Administrator6 *7*/8public class Detail {9//ID10private Integer detailId;11//外键 暂时可以忽略12private Integer orderId;13public Integer getDetailId() {14return detailId;15 }16public void setDetailId(Integer detailId) {17this.detailId = detailId;18 }19public Integer getOrderId() {20return orderId;21 }22public void setOrderId(Integer orderId) {23this.orderId = orderId;24 }25public Integer getQuantity() {26return quantity;27 }28public void setQuantity(Integer quantity) {29this.quantity = quantity;30 }31public String getItemName() {32return itemName;33 }34public void setItemName(String itemName) {35this.itemName = itemName;36 }37//商品数量38private Integer quantity;39//商品数量40private String itemName;4142 }5.在service中定义⼀个接⼝并且实现它 OrderService代码如下:1package com.spring.service;3import com.spring.model.Detail;4import com.spring.model.Order;56public interface OrderService {7//插⼊订单和订单明细8public void saveOrderAndDetail(Order order,Detail detail);9 } OrderServiceImp代码如下:1package com.spring.service;23import org.springframework.transaction.annotation.Transactional;45import com.spring.dao.OrderDaoImp;6import com.spring.dao.detailDaoImp;7import com.spring.model.Detail;8import com.spring.model.Order;910/**11 * 服务层使⽤注解来实现事务管理12 *13 * @author Administrator14 *15*/1617public class OrderServiceImp implements OrderService {18// 注⼊两个对象19public OrderDaoImp OrderDaoImp;2021public detailDaoImp detailDaoImp;2223 @Transactional24 @Override25// 如果加上@Transaction时,⽅法执⾏有异常,整个事务数据都会回滚,数据库中不会存在有数据。
spring事务管理全解析
spring事务管理全解析事务是一组原子(Atomic)操作的工作单元,以数据库存取的实例来说,就是一组SQL指令,这一组SQL指令必须全部执行成功,若因为某个原因未全部执行成功(例如其中一行SQL有错误),则先前所有执行过的SQL指令都会被撤消。
JDBC是如何控制事务的try ...{.....connection.setAutoCommit(false);.....// 一连串SQL操作mit();} catch(SQLException) ...{// 发生错误,撤消所有变更connection.rollback();}Spring是把JDBC事务管理进来了封装,Spring事务管理的抽象关键在于org.springframework.transaction.PlatformTransactionManager接口里面有commit 和rollbackpublic interface PlatformTransactionManager ...{TransactionStatus getTransaction(TransactionDefinitiondefinition) throws TransactionException;void commit(TransactionStatus status)throws TransactionException;void rollback(TransactionStatus status)throws TransactionException;}TransactionDefinition接口的实例定义了事务的隔离程度(Isolation level)传播行为(Propagation behavior)超时(Timeout)只读(Read-only)等DataSourceTransactionManager、HibernateTransactionManager、JdoTransaction- Manager、JtaTransactionManager等是实现了该接口Spring提供编程式的事务管理(Programmatic transaction management)与声明式的事务管理(Declarative transaction management):1、编程式的事务管理可以清楚地控制事务的边界,也就是让您自行实现事务开始时间、撤消操作的时机、结束时间等,可以实现细粒度的事务控制。
Springbootjpa删除数据和事务管理的问题实例详解
Springbootjpa删除数据和事务管理的问题实例详解今天我们介绍的是jpa删除和事务的⼀些坑,接下来看看具体内容。
业务场景(这是⼀个在线考试系统)和代码:根据问题的id删除答案repository层:int deleteByQuestionId(Integer questionId);service 层:public void deleteChoiceAnswerByQuestionId(Integer questionId) {choiceAnswerRepository.deleteByQuestionId(questionId);测试层:@Testpublic void testDeleteByQuestionId() {choiceAnswerService.deleteChoiceAnswerByQuestionId(5);System.out.println("hehehhe");System.out.println("hehehhe");System.out.println("hehehhe");System.out.println("hehehhe");System.out.println("hehehhe");System.out.println("hehehhe");System.out.println("hehehhe");}问题1:如果各层都不加事务管理的话@Transactional会报这个错误org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process ‘remove' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process ‘remove' call当我们除了query外的modiy和delete外如果没有各层的⽅法中进⾏事务管理的话也就是没加@Transactional话会报错问题2:只在test层加@Transactional没有错误但是数据并没有被删除,在⽤IDEA的调试是,在执⾏这个测试⽅法的过程时还可以在choiceanswer表中进⾏操作并没有加锁事务并没有起作⽤问题3:只在 Repository层加@Transactionalpublic void deleteChoiceAnswerByQuestionId(Integer questionId) {choiceAnswerRepository.deleteByQuestionId(questionId);System.out.println(“hehehhe”);System.out.println("hehehhe");// questionRepository.delete(5);System.out.println(“hehehhe”);System.out.println("hehehhe");System.out.println("hehehhe");System.out.println("hehehhe");System.out.println("hehehhe");}这时当执⾏完choiceAnswerRepository.deleteByQuestionId(questionId);数据⾥⾯被修改问题4:只在 service层加@Transactional当只有执⾏完service内的对应⽅法时数据才会被删除问题5:在service 层和Repository都加上@transactional当只有执⾏完service内的对应⽅法时数据才会被删除问题6:只要在test(或者是除了service层和Repository层)加上@Transactional,不管service层和Repository层加不加@Transactional数据都不会被删除问题7:@Modifying@Query(“delete from ChoiceAnswer c where c.question.id=?1 “)@Transactionalint deleteByQuestionId(Integer questionId);与@Transactionalint deleteByQuestionId(Integer questionId);有什么区别,上⾯的会直接执⾏delete语句下⾯的会先执⾏select 再执⾏delete总结:事务管理只有在service加上事务管理才起作⽤,query不需要事务管理但是delete update但需要事务管理为了不在Service层不加事务管理可以再Repository层的delete uodate加上@transactional 但这样不能真正保持事务的完整性.本⽂关于Spring boot jpa 删除数据和事务管理的问题实例详解的介绍就到这⾥,希望对⼤家有所帮助,欢迎⼤家参阅本站其他专题。
JavaEE——Spring4--(9)Spring的事务管理(注解方式)
JavaEE——Spring4--(9)Spring的事务管理(注解⽅式)⽤来确保数据的完整性和⼀致性.事务的四个关键属性(ACID)原⼦性(atomicity):事务是⼀个原⼦操作, 由⼀系列动作组成. 事务的原⼦性确保动作要么全部完成要么完全不起作⽤.⼀致性(consistency):⼀旦所有事务动作完成, 事务就被提交. 数据和资源就处于⼀种满⾜业务规则的⼀致性状态中.隔离性(isolation):可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防⽌数据损坏.持久性(durability):⼀旦事务完成, ⽆论发⽣什么系统错误, 它的结果都不应该受到影响. 通常情况下, 事务的结果被写到持久化存储器中.1.基于注解的导⼊相应的jar包 mysql C3P0 和Spring的AOP的<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd /schema/context /schema/context/spring- <!--扫描包--><context:component-scan base-package="jdbc"></context:component-scan><!--导⼊资源⽂件--><context:property-placeholder location="classpath:db.properties"/><!--配置C3P0数据源--><bean id="dataSource" class="boPooledDataSource"><property name="user" value="${er}"></property><property name="password" value="${jdbc.password}"></property><property name="driverClass" value="${jdbc.driverClass}"></property><property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property><property name="initialPoolSize" value="${jdbc.initPoolSize}"></property><property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property></bean><!--配置Spring的JDBCTemplate--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean></beans> 相应的db.propertieser=rootjdbc.password=1234jdbc.driverClass=com.mysql.jdbc.Driverjdbc.jdbcUrl=jdbc:mysql://localhost:3306/db_personjdbc.initPoolSize=5jdbc.maxPoolSize=10⾸先配置组件扫描<context:component-scan base-package="jdbc"></context:component-scan>在xml配置了这个标签后,spring可以⾃动去扫描base-pack下⾯或者⼦包下⾯的java⽂件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean再写出连接数据库后需要做的事情(增删改查)1.写增删改查的接⼝package jdbc.transactionManager;public interface BookShopDAO {//根据书号获取单价public double findPriceByIsbn(String isbn);//更新书的库存,使书号对应的库存-1public void updateBookStock(String isbn);//更新账户余额使username的balance-pricepublic void updateUserAccount(String username, double price);} 实现增删改查接⼝记得在实现的类上标上注解@Repository("bookShopDAO")还有 @Autowiredpackage jdbc.transactionManager;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;@Repository("bookShopDAO")public class BookShopDAOImpl implements BookShopDAO {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic double findPriceByIsbn(String isbn) {String sql = "SELECT price FROM book WHERE isbn = ?";return jdbcTemplate.queryForObject(sql, Double.class, isbn);}@Overridepublic void updateBookStock(String isbn) {//要检查书的库存是否⾜够,不够的话,要抛出异常String sql2 = "SELECT stock FROM book_stock WHERE isbn = ?";int stock = jdbcTemplate.queryForObject(sql2, Integer.class, isbn);if(stock == 0){throw new BookStockException("库存不⾜");}String sql = "UPDATE book_stock SET stock = stock - 1 WHERE isbn = ?";jdbcTemplate.update(sql, isbn);}@Overridepublic void updateUserAccount(String username, double price) {//要检查⽤户的余额,不够的话,要抛出异常String sql2 = "SELECT balance FROM account WHERE username = ?";double balance = jdbcTemplate.queryForObject(sql2, Double.class, username);if(balance <= price){throw new UserAccountException("余额不⾜");}String sql = "UPDATE account SET balance = balance - ? WHERE username = ?";jdbcTemplate.update(sql, price, username);}}注意判断条件,若不符合条件的抛出异常⾃⼰定义的异常⾸先要继承RunTimeException 然后写全部的构造器package jdbc.transactionManager;public class BookStockException extends RuntimeException {private static final long serialVersionUID = 1L;public BookStockException() {}public BookStockException(String message) {super( message );}public BookStockException(String message, Throwable cause) {super( message, cause );}public BookStockException(Throwable cause) {super( cause );}public BookStockException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super( message, cause, enableSuppression, writableStackTrace );}} 进⾏查询购买1.先写购买的接⼝package jdbc.transactionManager;public interface BookShopService {//顾客买书public void purchase(String username, String isbn);}2.在实现该接⼝在实现该购买接⼝时,注意在对应的⽅法上⾯添上事务注解@Transactional这样购买的流程就会成为⼀个事务,当余额或库存不⾜时,不会完成事务,会发⽣回滚package jdbc.transactionManager;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;@Service("bookShopService")public class BookShopServiceImpl implements BookShopService{@Autowiredprivate BookShopDAO bookShopDAO;//添加事务注解@Transactional@Overridepublic void purchase(String username, String isbn) {//获取书的单价double price = bookShopDAO.findPriceByIsbn(isbn);//更新书的库存bookShopDAO.updateBookStock(isbn);//更新⽤户的余额bookShopDAO.updateUserAccount(username, price);}} 注意还要在xml中进⾏事务配置<!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!--启⽤事务注解--><tx:annotation-driven transaction-manager="transactionManager"/> 完整的xml配置⽂件如下<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context" xmlns:tx="/schema/tx"xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd /schema/context /schema/cont <!--扫描包--><context:component-scan base-package="jdbc"></context:component-scan><!--导⼊资源⽂件--><context:property-placeholder location="classpath:db.properties"/><!--配置C3P0数据源--><bean id="dataSource" class="boPooledDataSource"><property name="user" value="${er}"></property><property name="password" value="${jdbc.password}"></property><property name="driverClass" value="${jdbc.driverClass}"></property><property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property><property name="initialPoolSize" value="${jdbc.initPoolSize}"></property><property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property></bean><!--配置Spring的JDBCTemplate--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!--启⽤事务注解--><tx:annotation-driven transaction-manager="transactionManager"/></beans>。
spring注解式事务管理实例
spring注解式事务管理实例⼀.spring配置⽂件这⾥使⽤spring命名空间,如下:<context:property-placeholder location="classpath:jdbc.properties" /><bean id="dataSource" class="mons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName" value="${jdbc.driverClassName}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${ername}" /><property name="password" value="${jdbc.password}" /><property name="initialSize" value="${jdbc.initialSize}" /><property name="maxActive" value="${jdbc.maxActive}" /><property name="maxIdle" value="${jdbc.maxIdle}" /><property name="minIdle" value="${jdbc.minIdle}" /><property name="maxWait" value="${jdbc.maxWait}" /></bean><!-- 设定transactionManager --><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!--启动spring注解功能--><tx:annotation-driven transaction-manager="transactionManager" /></beans>说明:1.如果事务管理器的id是transactionManager,这⾥可以不对transaction-manager进⾏配置,即<tx:annotation-driven />就可以。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Spring中的事务管理实例详解
本文实例讲述了Spring中的事务管理。
分享给大家供大家参考。
具体分析如下:事务简介:事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性事务就是一系列的动作,它们被当作一个单独的工作单元。
这些动作要么全部完成,要么全部不起作用事务的四个关键属性(ACID)①原子性(atomicity):事务室一个原子操作,有一系列动作组成。
事务的原子性确保动作要么全部完成,要么完全不起作用
②一致性(consistency):一旦所有事务动作完成,事务就被提交。
数据和资源就处于一种满足业务规则的一致性状态中
③隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏
④持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。
通常情况下,事务的结果被写到持久化存储器中Spring中的事务管理作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层。
而应用程序开发人员不必了解底层的事务管理API,就可以使用Spring的事务管理机制。
Spring既支持编程式事务管理,也支持声明式的事务管理编程式事务管理:将事务
管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码声明式事务管理:大多数情况下比编程式事务管理更好用。
它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
事务管理作为一种横切关注点,可以通过AOP方法模块化。
Spring通过Spring AOP框架支持声明式事务管理。
Spring事务的传播属性:当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。
例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
事务的传播行为可以由传播属性指定。
Spring定义了7种传播行为:Spring支持的事务传播行为传播行为含义PROPAGATION_MANDATORY 表示该
方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常PROPAGATION_NESTED 表示如果当前已经存
在一个事务,那么该方法将会在嵌套事务中运行。
嵌套的事务可以独立于当前事务进行单独地提交或回滚。
如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。
注意各厂商对这种传播行为的支持是有所差异的。
可以参考资源管理器的文档来确认它们是否支持嵌套事务PROPAGATION_NEVER表示当前方法不应该运行在
事务上下文中。
如果当前正有一个事务在运行,则会抛出异常PROPAGATION_NOT_SUPPORTED 表示该方法不应
该运行在事务中。
如果存在当前事务,在该方法运行期间,当前事务将被挂起。
如果使用JTATransactionManager的话,则需要访问TransactionManager
PROPAGATION_REQUIRED 表示当前方法必须运行在事务中。
如果当前事务存在,方法将会在该事务中运行。
否则,会启动一个新的事务PROPAGATION_REQUIRED_NEW 表示当前方法必须运行在它自己的事务中。
一个新的事务将被启动。
如果存在当前事务,在该方法执行期间,当前事务会被挂起。
如果使用JTATransactionManager的话,则需要访问TransactionManager PROPAGATION_SUPPORTS 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行。