**JAVA项目中的事务管理

事务:保证一组对数据库操作动作的完整性(一致性, 安全性),也就是说:这一组动作要么都成功,要么都失败

1.JDBC对事务的支持

  • Java应用传统上使用JDBC(Java Database Connectivity)API来把数据持久到关系数据库中
  • JDBC 事务是用 Connection 对象控制的
    JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交(默认)和手动提交
  • 自动提交时(setAutoCommit(true)),每个独立SQL操作的执行完毕,事务会立即自动提交,也就是说每个SQL操作都是一个事务。
  • 一个独立SQL操作什么时候算执行完毕?
    对数据操作语言(DML,如insert,update,delete)和数据定义语言(如create,drop),语句一执行完就视为执行完毕。
    对select语句,当与它关联的ResultSet对象关闭时,视为执行完毕。
    对存储过程或其他返回多个结果的语句,当与它关联的所有ResultSet对象全部关闭,所有update count(update,delete等语句操作影响的行数)和output parameter(存储过程的输出参数)都已经获取之后,视为执行完毕。

例:

package com.ksxx.jdbc.pm;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;import com.ksxx.jdbc.util.DBUtil;/*** 事务控制*      雷锋 → rose 转账 500*          step1:雷锋 转出step2:rose 收款*/
public class TransactionDemo {public static void main(String[] args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = DBUtil.getConn();conn.setAutoCommit(false);//关闭数据库连接的自动提交功能//******雷锋向rose转账 start***********************************String sql = "update userinfo set account = account - 500 "+"where username = '活雷锋'";    //雷锋 转出ps = conn.prepareStatement(sql);ps.executeUpdate();String str = null;//模拟异常出现str.toString();sql = "update userinfo set account = account + 500 " +"where username = 'rose'";   // rose 收款ps = conn.prepareStatement(sql);ps.executeUpdate();//******雷锋向rose转账 end*************************************conn.commit();//如果事务执行完毕,手动提交。} catch(Exception e){try {conn.rollback();//事务过程中,发生异常,数据回滚。} catch (SQLException e1) {e1.printStackTrace();}e.printStackTrace();} finally{try {//将数据库连接交还给连接池时,必须要重新开启事务的自动提交功能conn.setAutoCommit(true);} catch (SQLException e) {e.printStackTrace();}DBUtil.closeConn(rs, ps, conn);//将数据库连接交还给连接池}}}

2.MyBatis框架中事务处理

  • MyBatis单独使用时:使用SqlSession来处理事务

DAO模块代码

public interface CostDao {//Mapper映射器 本质就是一个接口的定义规则//MyBatis是通过动态代理封装了实现类的代码//接口中的方法名和sql文件中的id保持一致//参数类型和sql文件中的parameterType指定类型一致//返回值参考ResultTypepublic void update(Map<String, Object> map);public void delete(int id);
}

CostMapper.xml文件

<mapper namespace="org.dao.CostDao"><update id="update" parameterType="map">update cost set status = '1', startime = #{startime} where cost_id = #{cost_id}</update><delete id="delete" parameterType="java.lang.Integer">delete from cost where cost_id = #{cost_id}</delete>
</mapper>

SqlMapConfig.xml文件

<configuration><environments default="environment"><environment id="environment"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver" value="oracle.jdbc.driver.OracleDriver" /><property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/><property name="username" value="ksxx_26" /><property name="password" value="ksxx_26" /></dataSource></environment></environments><!-- 加载sql文件 --><mappers><mapper resource="org/sql/CostMapper.xml" /></mappers>
</configuration> 

创建一个SqlSession工具类

public class MyBatisUtil {public static SqlSession getSqlSession(){SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();  //加载sqlMapConfig.xml文件InputStream is = MyBatisUtil.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");//创建SessionFactory对象SqlSessionFactory sf = builder.build(is);//创建sessionSqlSession ss = sf.openSession();   return ss;}
}

Junit单元测试

@Test
public void test3() throws SQLException{SqlSession ss = MyBatisUtil.getSqlSession();TransactionFactory transactionFactory = new JdbcTransactionFactory();//开启事务Transaction newTransaction = transactionFactory.newTransaction(ss.getConnection());try {Map<String, Object> map = new HashMap<String, Object>();Timestamp time = new Timestamp(System.currentTimeMillis());map.put("startime", time);map.put("cost_id", 1);int row = ss.update("update", map);//修改行数ss.delete("delete", 147);ss.commit();//执行完毕手动提交} catch (Exception e) {newTransaction.rollback();//出现异常回滚e.printStackTrace();} finally {newTransaction.close();//关闭事务ss.close();//关闭seesion连接}
}

3.MyBatis和Spring整合后, 使用Spring的事务管理

  • Spring提拱了编程式配置事务和声明式配置事务
    编程式事务处理对代码有些侵入性,通常我们的事务需求并没有要求在事务的边界上进行如此精确的控制。因此一般采用声明式事务管理
    声明式事务有两种方式:@Transactional注解方式和XML配置方式
  • Spring如何管理事务呢???
    Spring会从datasource里面去获得连接
    Spring需要操作事务,那必须要对Connection来进行设置(Connection对象里面有对应的方法,比如setAutoCommit,commit,rollback这些方法就是对事务的操作)
    Spring的AOP可以拦截业务处理方法,并且也知道业务处理方法里面的DAO操作是从datasource里面获取Connection对象的
    既然Spring得到了datasource内部的Connection对象,便可以对当前拦截的业务处理方法进行事务控制了

方式一: @Transactional注解方式配置AOP事务

DAO中代码

public interface EmpDao {public void save(Emp emp);
}

EmpMapper.xml文件代码

<mapper namespace="org.ks.dao.EmpDao"><!-- 主键映射1.keyProperty ,实体对象对应的主键属性,当查完序列后,会将序列值赋给主键属性 empno2.order  BEFORE:先执行selectKey,在执行insertAFTER:执行顺序与BEFORE相反 --><insert id="save" parameterType="org.ks.entity.Emp"><selectKey keyProperty="empno"order="BEFORE" resultType="java.lang.Integer">select emp_seq.nextval from dual</selectKey>insert into emp values(#{empno},#{ename,jdbcType=VARCHAR},#{job,jdbcType=VARCHAR},#{mgr,jdbcType=NUMERIC},#{hiredate,jdbcType=DATE},#{sal,jdbcType=NUMERIC},#{comm,jdbcType=NUMERIC},#{deptno,jdbcType=NUMERIC})</insert>

applicationContext.xml文件配置

<util:properties id="jdbc" location="classpath:db.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName" value="#{jdbc.driverName}"/><property name="url" value="#{jdbc.url}"/><property name="username" value="#{jdbc.userName}"/><property name="password" value="#{jdbc.password}"/></bean><!-- 1.声明事务管理组件:定义具体平台事务管理器 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>   </bean><!-- 2.开启事务组件注解扫描:注册事务注解处理器如果方法发生运行期错误unchecked(RuntimeException),事务会进行回滚 如果发生checked Exception,事务不进行回滚. --><tx:annotation-driven transaction-manager="txManager"proxy-target-class="true"/>

Controller组件

@Controller
@RequestMapping("/emp")
@Transactional
public class EmpController {@Resourceprivate EmpDao empDao;/** 模拟批量添加员工*/@RequestMapping("/addemps.do")public String addBatch(){//插入第一个员工Emp e1=new Emp();e1.setEname("李梅");e1.setJob("老师");e1.setSal(1000.0);e1.setEmpno(10);empDao.save(e1);//模拟异常//Integer.valueOf("abc");//NumberFormatException//插入第二个员工Emp e2=new Emp();e2.setEname("李刚");e2.setJob("老师");e2.setSal(2000.0);e2.setEmpno(20);empDao.save(e2);return "emp/emp_list";}
}

方式二:通过xml配置AOP事务

<!-- 1.声明事务管理组件:定义具体平台事务管理器 --><bean id="txManager" class=     "org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>   </bean>
<!-- 2.基于xml配置的声明事务范围及类型  定义通知, 通知中要处理的就是事务 --><tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><!-- 配置具体方法事务属性isolation:事务隔离级别,默认为数据库隔离级别   propagation:事务传播行为:默认是同一事务timeout="-1":事务超时时间,默认值使用数据库的超时时间read-only="false":事务是否只读,默认是可读写rollback-for:遇到那些异常就回滚,其他都不回滚no-rollback-for:遇到那些异常不会滚, 其他都回滚        --><tx:method name="save"  propagation="REQUIRED" isolation="DEFAULT" read-only="false" rollback-for="java.lang.NullPointException"/><!-- 支持通配符 --><tx:method name="find*" read-only="true"/><tx:method name="add*"/><tx:method name="update*"/><tx:method name="delete*"/></tx:attributes></tx:advice><!-- 3.配置aop --><aop:config proxy-target-class="true"><!-- 切入点 --><aop:pointcut expression="within(org.ks.controller..*)" id="txPointcut"/> <!-- 配置切面 --><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/></aop:config><context:component-scan base-package="org.ks"/><mvc:annotation-driven/><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/"/><property name="suffix" value=".jsp"/></bean><!-- 定义SqlSessionFactoryBean 将MyBatis中的主配置文件中的重要参数引入spring配置文件中 ,这样MyBatis的主配置文件就可以不用了--><bean id="ssf" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 注入连接信息 --><property name="dataSource" ref="dataSource"/><!-- 注入sql定义文件信息,若是多个Mapper文件 可以使用*代替 --><property name="mapperLocations" value="classpath:org/ks/sql/*.xml"/></bean><!-- 配置MapperScannerConfigurer 按指定包扫描接口,批量生成接口实例对象,默认接口名首字母小写当id --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!-- 指定扫描包,会扫描此包及其子包下的接口,多个包之间可以用“,"隔开 --><property name="basePackage" value="org.ks.dao"/><!-- 注入sqlSessionFactoryBean 可以写也可不写,会自动注入 --><property name="sqlSessionFactory" ref="ssf"/></bean>

JAVA项目中的事务管理相关推荐

  1. 项目中spring事务管理配置分析与修改方案

    概要: 现有spring事务管理配置存在问题:对数据库无关的service层方法,也会进行事务管理(创建数据库链接.提交(回滚)事务.释放连接等),消耗资源. 修改方案:只对执行数据库写操作的serv ...

  2. Spring(四)——AOP、Spring实现AOP、Spring整合Mybatis、Spring中的事务管理

    文章目录 1. 什么是AOP 2. 使用Spring实现AOP 2.1 使用Spring的API 接口实现 2.2 自定义实现 2.3 使用注解实现 3. 整合MyBatis 3.1 MyBatis- ...

  3. 基于Spring中的事务管理机制

    什么是事务? 通俗理解,事务其实就是一系列指令的集合. 为什么要使用事务管理? 我们在实际业务场景中,经常会遇到数据频繁修改读取的问题.在同一时刻,不同的业务逻辑对同一个表数据进行修改,这种冲突很可能 ...

  4. Spring中进行事务管理的两种方式

    1.Spring中事务管理的API 事务是指逻辑上要么全部成功.要么全部失败的一组操作.例如用户A给用户B转账,则用户A账户余额减少.用户B账户增加这两个操作就是一组事务,必须全部成功或失败撤回操作, ...

  5. Quartz-2.2.1 任务调度框架在Java项目中的使用实例

    < Quartz-2.2.1 任务调度框架在Java项目中的使用实例 > 本实例是基于Quartz 2.2.1 版本为中心,也是目前最新的Quartz任务调度框架. 目前在 J2EE 项目 ...

  6. Spring中的事务管理详解

    在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...

  7. 为什么在2012/2013年我将在新的Enterprise Java项目中继续使用Spring *和* Java EE

    自从我担任技术决策职务以来已经过去了一年多,很高兴看到我仍然与之保持着完美的和谐. 几个月前,我在KaiWähner的一个不错的博客中写了一个有关JEE与Spring的答案. 如果观点没有不同,那么讨 ...

  8. 为什么我会在2012年的新企业Java项目中使用Java EE而不是Spring

    这个问题经常出现. 我的新项目也在2011年11月发布. 在这个新的Enterprise Java项目中,我将使用Java EE(JEE)代替Spring框架. 我知道:关于此主题的文章,博客和论坛讨 ...

  9. spring事务管理器的作用_【面试必问】Spring中的事务管理详解

    在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...

最新文章

  1. 编写jQueryUI插件(widget)
  2. sublime Text 2 安装Sublime Package Control
  3. Hadoop2.2.0集群在RHEL6.2下的安装实战
  4. ASP.NET中应用的监视
  5. p沟道mos管导通条件_通俗易懂:MOS管基本知识(快速入门)
  6. 详谈Windows消息循环机制
  7. 亿佰特物联网通信专家:蓝牙模块和 Zigbee协议模块的区别
  8. tf.clip_by_value()
  9. qemu-kvm命令行参数
  10. linux 免密登录
  11. URAL 1586. Threeprime Numbers 数位dp
  12. Atitit 提升开发进度大方法--高频功能与步骤的优化 类似性能优化
  13. windows下odbc数据源配置
  14. Vrep学习笔记(一)
  15. Crosses and Crosses
  16. ArcGIS水文分析实战教程(4)地形预处理
  17. 办公电脑远程软件有哪些、这几款你知道吗
  18. Conflux DAO 社区技术委员会成立 助力生态繁荣发展
  19. IP地址、子网掩码、网络号、主机号、网络地址、主机地址以及ip段/数字-如192.168.0.1/24是什么意思?
  20. python 播放本地音乐_python播音乐_python放音乐_python本地音乐播放器 - 云+社区 - 腾讯云...

热门文章

  1. Java相关课程系列笔记之一Java学习笔记
  2. BIM IFC模型在线查看工具
  3. minecraft 局域网联机问题一个可能的解决办法
  4. 专业导论-课后总结-2019.11.29
  5. ViewPager添加小圆点
  6. SSDHDD混装换一块SSD(迁移系统与资料不重装)
  7. android 仿阅读,发布一个练笔的 Android 阅读器,轻微仿91 Android 阅读器【后续将提供源码】...
  8. div包video在某些电脑或者浏览器上出现黑边
  9. 科研学术一条龙框架与工具
  10. python画画用哪库好_Python我要学画画-turtle库