JDBC事务 Hibernate事务 EJB事务详解

这篇具有很好参考价值的文章主要介绍了JDBC事务 Hibernate事务 EJB事务详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

JDBC事务 Hibernate事务 EJB事务详解

 文章来源地址https://www.toymoban.com/news/detail-411645.html

🏆今日学习目标:

🍀JDBC事务 Hibernate事务 EJB事务详解
创作者:林在闪闪发光
⏰预计时间:30分钟
🎉个人主页:林在闪闪发光的个人主页

 🍁林在闪闪发光的个人社区,欢迎你的加入: 林在闪闪发光的社区

目录

一、JDBC事务

1.事务的概念

2.JDBC中事务的相关方法 

3.一个简单的示例

二、HIbernate中的事务

1.HIbernate中的事务管理

三、EJB事务 


当你想要某种东西时,整个宇宙会合力助你实现愿望

                                                                                      《牧羊少年奇幻之旅》

一、JDBC事务

1.事务的概念

事务(Transaction),字面理解,一般是指要做的或所做的事情。

在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由​​高级数据库​​​操纵语言或编程语言(如SQL,C++或Java)书写的​​用户程序​​的执行所引起,并用形如begin transactionend transaction语句(或​​函数调用​​)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。

上述解释来自百度百科,如果你学过操作系统,可以将事务理解成原语,事务中的每件不可分割的子任务可以视为一条指令

在我们今天要讲的数据库中的事务,就可以理解为一条或一组SQL语句,这个事务成功的执行的必要条件就是其中的SQL全部执行成功,如果其中的任一SQL执行失败(没有达到预期效果),则此次事务执行失败,所有的SQL都不会对数据库中的数据产生变更。

事务具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性

  • 原子性(Atomicity):一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做;
  • 一致性(Consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的;
  • 隔离性(Isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰;
  • 持久性(Durability):持久性也称永久性(Permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

​ 对于其中的隔离性,数据库服务器有时会为了提供更好的处理并发能力,会牺牲一定的隔离性。这也是正确性和性能之间的对抗。如MySQL默认的隔离级别为READ COMMITTED,即读提交,可以读取其他事务已经提交的内容,可以避免脏读,但是无法避免​​重复度和幻读​​。

2.JDBC中事务的相关方法 

下面我们来看下,当使用JDBC操作数据库时,要如何使用事务。这里,我们要新介绍几个Connection接口中的几个方法,如下表所示:

JDBC事务 Hibernate事务 EJB事务详解

当Connection自动提交模式为true的时候,即默认值,其所有SQL语句将作为单个事务执行并提交,每次SQL执行时会默认提交,不需手动触发;当自动提交模式为false时,其SQL语句会分组为事务(commit与commit之间的SQL或commit与rollback之间的SQL),这些事务通过调用​​commit​​方法提交,或调用​​rollback​​方法来进行回滚。

3.一个简单的示例

正常情况

public class TestTransaction1 {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            con = JDBCUtils.getConnection();
            //关闭自动提交 自动会开启事务
            con.setAutoCommit(false);//开启事务
            // A 转 B 100元
            String sql1 = "update account set money=money-100 where name='A'";
            st = con.prepareStatement(sql1);
            st.executeUpdate();
            String sql2 = "update account set money=money+100 where name='B'";
            st = con.prepareStatement(sql2);
            st.executeUpdate();
            //业务完毕,提交事务
            con.commit();

            System.out.println("A 转 B 100元 成功!");
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                con.rollback();   //如果失败就回滚事务
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } finally {
            JDBCUtils.release(con, st, rs);
        }
    }
}

异常情况

public class TestTransaction2 {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            con = JDBCUtils.getConnection();
            //关闭自动提交 自动会开启事务
            con.setAutoCommit(false);//开启事务
            // A 转 B 100元
            String sql1 = "update account set money=money-100 where name='A'";
            st = con.prepareStatement(sql1);
            st.executeUpdate();

            //int x=1/0;   //报错

            String sql2 = "update account set money=money+100 where name='B'";
            st = con.prepareStatement(sql2);
            st.executeUpdate();
            //业务完毕,提交事务
            con.commit();

            System.out.println("A 转 B 100元 成功!");
        } catch (SQLException e) {
            //如果失败则会默认回滚
            e.printStackTrace();
            /*try {
                con.rollback();   //如果失败就回滚事务
            } catch (SQLException ex) {
                ex.printStackTrace();
            }*/
        } finally {
            JDBCUtils.release(con, st, rs);
        }
    }
}

二、HIbernate中的事务

1.​​​​​​​HIbernate中的事务管理

在Hibernate中,可以通过代码来操作管理事务,如通过“Transaction tx = session.beginTransaction();” 开启一个事务:持久化操作后,通过“tx.commit();” 提交事务;如果事务出现异常,又通过“tx.rollback();” 操作来撤销事务(事务回滚)。

除了在代码中对事务开启,提交和回滚操作外,还可以在Hibernate的配置文件中对事务进行配置。配置文件中,可以设置事务的隔离级别。具体的配置方法是在hibernate.cfg.xml 文件中的 标签元素中进行的。如下:

		<!-- 指定hibernate操作数据库时的隔离级别 
			#hibernate.connection.isolation 1|2|4|8		
			0001	1	读未提交
			0010	2	读已提交
			0100	4	可重复读
			1000	8	串行化
		 -->
		 <property name="hibernate.connection.isolation">4</property>

 我们在真正进行事务管理的时候,需要考虑事务的应用场景,也就是说我们的事务控制不应该是在DAO层实现的,应该在Service层实现,并且在Service中调用多个DAO实现一个业务逻辑的操作。
具体操作如下显示:

JDBC事务 Hibernate事务 EJB事务详解

JDBC事务 Hibernate事务 EJB事务详解 

其实最主要的是如何保证在Service中开启的事务时使用的Session对象和DAO中多个操作使用的是同一个Session对象。
其实由两种办法可以实现:

  • 可以在业务层获取到Session,并将Session作为参数传递给DAO。
  • 可以使用ThreadLocal 将业务层获取的Session绑定到当前线程中,然后在DAO中获取Session的时候,都从当前线程中获取。

其实使用第二种方式肯定是最优方案,那么具体的实现已经不用我们来完成了,Hibernate的内部已经帮我们将这个事情做完了。我们只需要完成一段配置即可。

Hibernate5 中自身提供了三种管理Session对象的方法:

  • t h r e a d : S e s s i o n 对 象 的 生 命 周 期 与 本 地 线 程 绑 定 。 \color{red}{thread:Session对象的生命周期与本地线程绑定。} thread:Session对象的生命周期与本地线程绑定。
  • jta:Session 对象的生命周期与 JTA 事务绑定。
  • managed:Hibernate委托程序来管理Session对象的生命周期。

在hibernate.cfg.xml 中进行如下配置:

		<!-- 指定session与当前线程绑定 -->
		 <property name="hibernate.current_session_context_class">thread</property>

 

Hibernate提供sessionFactory.getCurrentSession() 创建一个session 和ThreadLocal 绑定方法。

书写一个HibernateUtils工具类:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtils {
	private static SessionFactory sf;
	
	static{
		//1 创建,调用空参构造
		Configuration conf = new Configuration().configure();
		//2 根据配置信息,创建 SessionFactory对象
		 sf = conf.buildSessionFactory();
	}
	
	//获得session => 获得全新session
	public static Session openSession(){
		//3 获得session
		Session session = sf.openSession();
		return session;
	}
	
	//获得session => 获得与线程绑定的session
	public static Session getCurrentSession(){
		//3 获得session
		Session session = sf.getCurrentSession();
		return session;
	}
	
}

而且Hibernate中提供的这个与线程绑定的session可以不用关闭,当线程执行结束后,就会自动关闭了。

测试方法:



import org.hibernate.Session;
import org.junit.Test;

import pers.zhang.utils.HibernateUtils;

//测试getCurrentSession
public class Demo {

	@Test
	//返回同一个与线程绑定的session
	public void fun1(){
		Session session1 = HibernateUtils.getCurrentSession();
		Session session2 = HibernateUtils.getCurrentSession();
		
		System.out.println(session1==session2);//true
	}
	
	@Test
	//返回不同的session
	public void fun2(){
		Session session1 = HibernateUtils.openSession();
		Session session2 = HibernateUtils.openSession();
		
		System.out.println(session1==session2);//false
	}
	
	
}

输出

true

false

三、EJB事务 

在我们对事务的基本概念以及出现的问题和隔离级别有进一步的了解之后,接下来看看EJB是如何进行事务管理.

       在EJB中有两种使用事务的方式。第一种方式通过容器管理的事务,叫CMT(Container-Managed Transaction),另一种通过Bean管理的事务叫BMT(Bean-Managed Transaction)。

       如果使用容器来管理事务,那么EJB组件就不需要显式地给出begin 、commit 、abort 语句,EJB 容器会替我们考虑这些内容。EJB 容器会依据EJB组件提供者指定的事务行为来界定相应的事务边界。

      在使用容器管理事务时,EJB 容器会拦截客户请求,并自动为EJB组建启动新的事务,也就是说,容器会通过begin 语句调用底层事务系统,从而启动事务。随后,容器会将业务请求委派给EJB组件,组件中的业务操作将运行在这一事务中。处于事务中的EJB 组件能够执行任何业务逻辑,如写入数据库、发送异步信息、调用其他的EJB组件等。一旦在处理业务过程中出现问题,则EJB 组建需要通知EJB 容器去回滚事务。当EJB 组建完成业务处理后,会将控制权交回给EJB 容器。随后,EJB容器能够通过commit 或abort 语句调用底层事务系统。

       我们可以使用@TransactionAttribute注释或部署描述符来指定事务属性。EJB 容器通过分析事务属性便能够知道如何处理EJB 组件的事务需求。

        如果用简短的话总结上面的内容就是,用CMT管理事务,事务都是被容器管理的,开发人员不需要对事务进行管理,需要做的就是配置事务属性.

      EJB 事务属性的取值有以下几种:

(1 )Required ,如果EJB组件必须总是运行在事务中,则应该使用Required 模式。如果已经有事务在运行,则EJB 组件参与其中;如果没有事务运行,则EJB 容器会为EJB组件启动新的事务。

          Required 是默认和最常使用的事务属性值。这个值指定必须在事务之内调用EJB方法。如果从非事务性客户端调用方法,那么容器会在调用方法之前开始事务,并且在方法返回时结束事务。另一方面,如果调用者从事务性上下文调用方法,那么方法会联结已有事务。在从客户段传播事务的情况下,如果我们的方法表示应该回滚事务,那么容器不仅回回滚整个事务,而且会向客户端抛出异常,从而让客户端知道它开始的事务已经被另一个方法回滚了。

(2 )Requires_New,当客户调用EJB 时,如果总是希望启动新的事务,则应该使用RequiresNew 事务属性,如果客户在调用EJB组件时已经存在事务,则当前事务会被挂起,进而容器启动新的事务,并将调用请求委派给EJB组件。也就是说,如果客户端已经有了事务,那么它暂停该事务,知道方法返回位置,新事务是成功还是失败都不会影响客户端已有的事务。EJB组件执行相应的业务操作,容器会提交或回滚事务,最终容器将恢复原有的事务,当然,如果客户在调用EJB 组件时不存在事务,则不需要执行事务的挂起或恢复操作。

          RequiresNew 事务属性非常有用。如果EJB 组件需要事务的ACID属性,并且将EJB 组件运行在单个独立的工作单元中,从而不会将其他外部逻辑也包括在当前的事务中,则必须使用RequiredNew事务属性。如果需要事务,但是不希望事务的回滚影响客户端,就应该使用它。另外,当不希望客户端的回滚影响你的时候,也应该使用这个值。

(3 )Supports ,如果某个EJB组件使用了Supports 事务属性,则只有调用它的客户已经启用了事务时,这一EJB 组件才会运行在事务中。如果客户并没有运行在事务中,则EJB组建也不会运行在事务中。Supports 同Required 事务属性很相似,但是,Required 要求EJB 组件必须运行在事务中。如果使用Support事务属性,EJB 组建很可能没有运行在事务中。

(4 )Mandatory ,Mandatory事务属性要求调用EJB 组件的客户必须已经运行在事务中。如果从非事务性客户端调用使用Mandatory 属性的EJB方法,那么客户将接受到系统抛出的javax.ejb.EJBTransactionRequiredException 异常。EJB 组件使用Mandatory事务属性是非常安全的,它能够保证EJB 组建运行在事务中。如果客户没有运行在事务中,则不能够调用到应用了Mandatory 事务属性的EJB组件。但是,Mandatory 事务属性要求第3 方(及客户)在调用EJB 组件前必须启动了事务。EJB 容器并不会为Mandatory事务属性自动启动新事务,这是同Support 事务属性的最主要区别。

(5 )NotSupported ,如果EJB组件使用了NotSupport事务属性,它根本不会参与到事务中。如果调用者使用相关联的事务调用方法,容器就会暂停事务,调用方法,然后再方法返回时恢复事务。通常,此属性只用于非实物性的自动确认模式中,支持JMS提供者的MDB 。

(6 )Never ,如果EJB组件使用Never 事务属性,它就不能够参与到事务中,而且,如果调用它的客户已经处于事务中,则容器会将javax.ejb.EJBException异常抛给客户。

当然在上面所列出的属性中我们最常用的还是Required具体可以看下面的一段片段代码:
 

 
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless(name = "UserManager")
@Remote
@TransactionManagement(TransactionManagementType.CONTAINER)
public class UserManagerBean implements UserManager {

	@PersistenceContext
	private EntityManager em ;
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void addUser(String name) {

		User s = new User();
		s.setName(name);
		em.persist(s);
		System.out.println("服务器端执行成功:保存姓名" + name);

	}

}

 

 上面的例子中

    @TransactionManagement(TransactionManagementType.CONTAINER)

表示指定事务的类型。如果省略,默认为CMT方式。

    @TransactionAttribute(TransactionAttributeType.REQUIRED)

通知容器如何管理事务,事务的属性控制了事务的使用范围,因为事务之间的关系非常的复杂,这个属性主要是用来处理事务与事务之间怎样来处理的的问题。

至此 事务已全部输出完毕 欢迎小伙伴补充

JDBC事务 Hibernate事务 EJB事务详解

 

到了这里,关于JDBC事务 Hibernate事务 EJB事务详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • spring boot 整合jdbc和事务

    目录 1、j在pom文件中引入dbc驱动与mybatis  2、数据库连接池参数配置 3、mybatis配置 4、application配置 5、通用mapper配置 6、编写UserMapper 7、user表(需要自行去mysql创建数据库表新增用户数据,sql语句见下一步) 8、sql信息 9、UserService编写 10、测试结果 11、测试输出结果 访问效果

    2024年02月15日
    浏览(31)
  • 高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤

    ✅作者简介:热爱后端语言的大学生,CSDN内容合伙人 ✨精品专栏:C++面向对象 🔥系列专栏:JDBC快速入门 一种合理的项目分层理念,好处为可以简化设计、各司其职、更容易扩展内容 三层架构分为: 表示层 (UI、WEB):跟用户对接 业务逻辑层 (service):书写功能的整体

    2024年02月16日
    浏览(32)
  • springboot第55集:思维导图Sharding-JDBC,事务,微服务分布式架构周刊

    事务定义 在数据库管理系统中,事务是单个逻辑或工作单元,有时由多个操作组成,在数据库中以一致模式完成的逻辑处理称为事务。一个例子是从一个银行账户转账到另一个账户:完整的交易需要减去从一个账户转账的金额,然后将相同的金额添加到另一个账户。 事务特

    2024年02月19日
    浏览(37)
  • EJB和Spring

    功能日趋复杂的软件,如果把所有的功能实现都放在客户端,不仅代码没有安全性,部署及发布运维都会变的很复杂,所以将软件的功能实现分为客户端和服务端,服务端和客户端之间通过网络调用进行功能实现。 客户端只做界面展示和数据交互,功能的实现统统交给服务端

    2024年04月28日
    浏览(15)
  • EJB基本概念和使用

    EJB是sun的JavaEE服务器端组件模型,是一种规范,设计目标与核心应用是部署分布式应用程序。 EJB2.0过于复杂,EJB3.0的推出减轻了开发人员进行底层开发的工作量,它取消或最小化了很多(以前这些是必须实现)回调方法的实现,并且降低了实体Bean及O/R映射模型的复杂性。 EJB大

    2024年02月12日
    浏览(28)
  • JDBC详解(一):JDBC概述

    本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注博主!也许一个人独行,可以走的很快,但是一群人结伴而行,才能走的更远! 1、概念 持久化( persistence ): 把数据保存到可掉电式存储设备中以供之后使用 。 大多数情况下,特

    2023年04月24日
    浏览(31)
  • JDBC详解(五):批量插入(超详解)

    本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注博主!也许一个人独行,可以走的很快,但是一群人结伴而行,才能走的更远! 当需要成批插入或者更新记录时,可以采用Java的批量 更新 机制,这一机制允许多条语句一次性提

    2024年02月02日
    浏览(69)
  • Java EE开发系列教程 - 使用EJB组件与JPA层交互

    因为之前JPA原生 property 属性在Wildfly实现中并不总是生效,所以这里换成了Wildfly默认的JPA实现,即Hibernate。把属性改成了Hibernate专有的。 hibernate.hbm2ddl.auto 定义是否自动生成表, create-and-drop 意为如果表存在,则删除后再创建。 hibernate.dialect 用来指定数据库厂商,以根据不同

    2024年04月13日
    浏览(26)
  • 详解JDBC各个对象

    概述:DriverManager 是驱动管理类 作用 获取数据库连接 url 语法 如果连接的是本机 MySQL 服务器,并且端口号默认则 url简写为: jdbc:mysql:///数据库名称 示例代码 概述:Connection 是数据库连接类 作用 获取执行 SQL 的对象 方法 作用 Statement createStatement(); 返回执行 SQL 对象 Prepared

    2024年01月20日
    浏览(25)
  • Java JDBC 详解

    目录 2、Java JDBC 的核心组件有哪些? 3、如何使用JDBC API? 4、DriverManager 和 DataSource 的区别 5、如何使用DataSource进行数据库连接?         Java JDBC (Java Database Connectivity)是Java语言中用于访问数据库的API。JDBC API提供了一组标准的接口,允许Java应用程序通过使用标准SQL查询语

    2024年02月02日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包