【问题标题】:How does a JBoss datasource failover handle failure in single transaction?JBoss 数据源故障转移如何处理单个事务中的故障?
【发布时间】:2016-05-01 06:58:29
【问题描述】:

这是我在 JBoss standalone.xml 中的连接详情

<connection-url>
    jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=xx.1xx.119.1xx)(PORT=1521))(LOAD_BALANCE=on)(FAILOVER=on))(CONNECT_DATA=(SERVICE_NAME=XE)))
</connection-url>

我想处理故障转移的极端情况,即在调用persist() 期间收到EntityManager 对象后,连接丢失。故障转移选项不是在同一个事务中切换到下一个数据库,而是在下一个事务中切换到活动连接。我尝试过这样的事情:(捕获异常并获取更新的 bean 对象)

public EntityManager getEntityManager() {
    try {
        entityManager = getEntityManagerDao(Constant.JNDI_NFVD_ASSURANCE_ENTITY_MANAGER);

    } catch (NamingException e) {
        LOGGER.severe("Data could not be persisted.");
        throw new PersistenceException();
    }
    return entityManager.getEntityManager();
}

/**
 * Inserts record in database. In case multiple connections/databases exist, one more attempt will be made to
 * insert record.
 *
 * @param entry
 */
public void persist(Object entry) {
    try {
        getEntityManager().persist(entry);
    } catch (PersistenceException pe) {
        LOGGER.info("Could not persist data. Trying new DB connection.");
        getEntityManager().persist(entry);
    }
}

private static Object getJNDIObject(String path) throws NamingException {
    Object jndiObject = null;
    InitialContext initialContext = new InitialContext();
    jndiObject = initialContext.lookup(path);
    return jndiObject;
}

private static AssuranceEntityManager getEntityManagerDao(String path) throws NamingException {
    return (AssuranceEntityManager) getJNDIObject(path);
}

但这一个也没有帮助。捕获异常后,使用 JNDI 查找获取新 bean 不包含更新的新连接并抛出异常。这会导致该交易的数据丢失。

请建议如何处理“连接丢失后获取 EntityManager 并在持久化之前”的极端情况。

【问题讨论】:

    标签: java jboss entitymanager failover


    【解决方案1】:

    我认为你想要达到的目标是完全不可能的。问题是,如果内部 DB 事务被中止,那么 JTA 事务处于中止状态,您无法继续。

    我希望它和这个案例有点相似

     @Stateless
     public class TableCreator {
        @Resource
        DataSource datasource;
    
        @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
        public void create() {
            try(Connection connection = datasource.getConnection()) {
                Statement st = connection.createStatement();
                st.execute("CREATE TABLE user (id INTEGER NOT NULL, name VARCHAR(255))");
            } catch (SQLException sqle) {
               // ignore this as table already exists
            }
        }
     }
    
     @Stateless
     public class Inserter {
       @EJB
       private TableCreator creator;
    
        public void call() {
            creator.create();
    
            UserEntity entity = new UserEntity(1, "EAP QE");
            em.persist(entity);
        }
     }
    

    如果表user 存在并且您将使用注释@TransactionAttribute(TransactionAttributeType.REQUIRED),则create 调用将与persist 调用属于同一jta 全局事务的一部分。在这种情况下,事务被中止,persist 调用将失败并出现异常,例如(postgresql 案例)

    Caused by: org.postgresql.util.PSQLException: ERROR: current transaction is aborted, commands ignored until end of transaction block
    

    我的意思是,如果 Oracle jdbc 驱动程序无法透明地处理与 JBoss 应用服务器的连接失败并向上抛出异常,那么我认为唯一可能的解决方案是重复整个更新操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多