database – UserTransaction中的Java多个数据库连接
发布时间:2020-12-15 04:35:29 所属栏目:Java 来源:网络整理
导读:static void clean() throws Exception { final UserTransaction tx = InitialContext.doLookup("UserTransaction"); tx.begin(); try { final DataSource ds = InitialContext.doLookup(Databases.ADMIN); Connection connection1 = ds.getConnection(); Co
static void clean() throws Exception { final UserTransaction tx = InitialContext.doLookup("UserTransaction"); tx.begin(); try { final DataSource ds = InitialContext.doLookup(Databases.ADMIN); Connection connection1 = ds.getConnection(); Connection connection2 = ds.getConnection(); PreparedStatement st1 = connection1.prepareStatement("XXX delete records XXX"); // delete data PreparedStatement st2 = connection2.prepareStatement("XXX insert records XXX"); // insert new data that is same primary as deleted data above st1.executeUpdate(); st1.close(); connection1.close(); st2.executeUpdate(); st2.close(); connection2.close(); tx.commit(); } finally { if (tx.getStatus() == Status.STATUS_ACTIVE) { tx.rollback(); } } } 我有一个Web应用程序,DAO将DataSource作为对象来创建单独的连接以执行数据库操作. 所以我有一个UserTransaction,里面有两个DAO对象做分离动作,第一个是做删除,第二个是做插入.删除是删除一些记录以允许插入,因为插入将插入相同的主键数据. 我拿出DAO层并将逻辑转换为上面的代码.有一点我无法理解,基于上面的代码,插入操作应该失败,因为代码(在UserTransaction内)采用两个不同的连接,它们彼此不认识,而第一个删除没有显然提交了,所以第二个语句(插入)应该失败(由于唯一约束),因为两个数据库操作不在同一个连接中,第二个连接不能检测未提交的更改.但令人惊讶的是,它并没有失败,这两种说法都可以完美地运作. 有人可以帮忙解释一下吗?可以通过任何配置来实现这一结果吗?或者我的理解是否错误? 解决方法
由于您的应用程序在weblogic服务器中运行,因此java-EE-container正在为您管理事务和连接.如果在java-ee事务中多次调用DataSource#getConnection,则会有多个Connection实例加入同一事务.通常这些连接使用相同的会话连接到数据库.使用oracle,您可以使用@Stateless ejb中的以下代码段检查:
@Resource(lookup="jdbc/myDS") private DataSource ds; @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) @Schedule(hour="*",minute="*",second="42") public void testDatasource() throws SQLException { try ( Connection con1 = ds.getConnection(); Connection con2 = ds.getConnection(); ) { String sessId1 = null,sessId2 = null; try (ResultSet rs1 = con1.createStatement().executeQuery("select userenv('SESSIONID') from dual") ){ if ( rs1.next() ) sessId1 = rs1.getString(1); }; try (ResultSet rs2 = con2.createStatement().executeQuery("select userenv('SESSIONID') from dual") ){ if ( rs2.next() ) sessId2 = rs2.getString(1); }; LOG.log( Level.INFO," con1={0},con2={1},sessId1={2},sessId2={3}",new Object[]{ con1,con2,sessId1,sessId2} ); } } 这会产生以下日志消息: con1=com.sun.gjc.spi.jdbc40.ConnectionWrapper40@19f32aa,con2=com.sun.gjc.spi.jdbc40.ConnectionWrapper40@1cb42e0,sessId1=9347407,sessId2=9347407 请注意,您将获得具有相同会话ID的不同Connection实例. 有关详细信息,请参阅例如this question (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |