JTA:java transaction api
java里所规定的一种管理事务的API
在另一篇播客我写到了,SessionFactory需要关注两个方法,
即: openSession 和 getCurrentSession
i. openSession 每次都是新的,需要close
ii. getCurrentSession 从上下文找,如果有,用旧的,如果没有,建新的
1,用途,界定事务边界
2,事务提交自动close
3,跟current_session_context_class (JTA、thread) 有关系
a)thread 使用 connection
下面就说说什么是上下文?
什么是上下文,是在配置文件hibernate.cfg.xml里指定的:
current_session_context_class:当前的session运行的环境的上下文。
<!-- Enable Hibernate's automatic session context management --> <property name="current_session_context_class">thread</property>
查hibernate的文档:
取值有四种:
1,jta *(重点说这个)
2,thread ***最常用
从当前线程里找,看有没有一个对象是 session,如果有,就用已经存在的,如果没有,就创建新的。
3,managed 极少用,可以忘了。
在J2ee里,EJB 的 Application Server 应用服务器,用来手工管理事务用managed,用的极少,可以忘了。
4,customer.class 没必要,可以忘了
自定义的class来管理currentSession。
先说结论:
事务有两种:
1,依赖于数据库本身的,简称Connection事务,只针对一个数据库。
2,JTA事务:分布式
我们这里指定的东西主要和事务有关系,如果指定的是thread,这时使用Connection(数据库连接)来帮你管理事务。connection.setAutoCommit(false),执行一系列操作,当catch到异常,connection.rollback(),没有异常,commit。但是有一种事务使用一个Connection是管理不了的,例:
处理订单:
DB1是产品数据库,DB2是财务的数据库。这两个数据库假设一个是mysql,一个是oracle,一个在北京,一个在上海。
要求客户端请求处理一个订单,往DB1里添加订单 (操作一),同时,向财务数据库DB2里记录财务信息(操作二),这两个操作必须在同一个事务里。
这时如果只有一个Connection,这两个操作就不能在一个事务里,目前的事务依赖于数据库本身的能力,还不能保证操作二出问题时,操作一也得回滚,保证不了。此时只有一个Connection是不行的。
这时需要一个专门的事务管理器,因为这种情况只依赖于数据库本身的Connection来管理事务是不行的
办法:
有一个Transaction Manager管理分布式事务(分布在多台不同的数据库server上)。
此时,先让Transaction Manager记录好操作一,操作二,,,做完操作,然后让Transaction Manager提交。Transaction Manager帮你管理着你的各个操作,假如第二个操作出了错,就要求第一个数据库的操作也回滚,这种能力的实现需要具体的数据库的驱动来实现,这时的驱动和我们在同一台服务器上做操作用的驱动不一样,是另外一种驱动,XA驱动 (J2ee要求的)。
Transaction Manager由Application Server(应用服务器)中间件来提供。tomcat本身目前不具备这个能力。(借助Spring可以实现)
Jboss支持,weblogic支持。这种事务就是JTA事务。
所以,只要你用getCurrentSession来得到session,必须要设定session运行的上下文。
如果在我们一般项目的配置里把上下文配置改为jta,或者不写
<property name="current_session_context_class">jta</property>
都会报错。因为Transaction Manager是由中间件,由application server应用服务器来提供,tomcat本身不具备这能力。如果你不设,就是被设置session运行的上下文,他就不知道去哪里找。