加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读