Jakarta ee 如何制作弹性EJB';可能引发系统异常(如PSQLException)的
我有一个运行在GlassFish 4.1中的EJB,它可能会偶尔抛出系统异常,比如PSQLException。在一种特定情况下,当尝试使用现有唯一键值将记录写入db时,会引发重复键异常。我尝试捕获所有异常,并将org.postgresql.util.PSQLException(和其他)作为异常类添加到applicationexception中的ejb-jar.xml中,但调用总是回滚事务。我希望我的EJB能够适应这些类型的异常。如果我能够捕获异常甚至忽略它们,我的应用程序就可以从这些问题中恢复。我怎样才能做到这一点 这里有一个例子。我有一个Servlet,当我用web浏览器点击它时,它会调用这个EJB方法:Jakarta ee 如何制作弹性EJB';可能引发系统异常(如PSQLException)的,jakarta-ee,exception-handling,ejb,rollback,glassfish-4.1,Jakarta Ee,Exception Handling,Ejb,Rollback,Glassfish 4.1,我有一个运行在GlassFish 4.1中的EJB,它可能会偶尔抛出系统异常,比如PSQLException。在一种特定情况下,当尝试使用现有唯一键值将记录写入db时,会引发重复键异常。我尝试捕获所有异常,并将org.postgresql.util.PSQLException(和其他)作为异常类添加到applicationexception中的ejb-jar.xml中,但调用总是回滚事务。我希望我的EJB能够适应这些类型的异常。如果我能够捕获异常甚至忽略它们,我的应用程序就可以从这些问题中恢复。
public void initialize() {
try {
User user = new User(0, "John", "Doe");
em.persist(user);
em.flush();
} catch(Exception e) {
e.printStackTrace();
}
我的ejb-jar.xml包含以下内容:
<application-exception>
<exception-class>org.postgresql.util.PSQLException</exception-class>
<rollback>false</rollback>
<inherited>true</inherited>
</application-exception>
org.postgresql.util.PSQLException
假的
真的
对我有效的解决方案是由高风险公司提供的。“解决方案是简单地将‘initialize’标记为非事务性,并将其放入一个单独的方法中,该方法在每次尝试时启动一个新事务。”
更新:这个解决方案不像我想的那样工作。我的申请中有一个错误,这使它看起来像是可行的。修复错误后,我又回到了同一个问题。PSQLException似乎不可捕获,因为它是一个系统异常。我尝试了容器管理和bean管理的方法。我不同意第二次尝试持久化记录会导致系统异常。在分布式环境中,这是可能发生的。这应该是一种可恢复的情况
更新:我使用下面发布的解决方案解决了我的问题。这肯定与JPA无关,它与PostgreSQL如何处理事务内部的错误状态有关 在您的情况下,它要么自动回滚到DB级别,要么将事务标记为处于不一致状态。您无法/不应该从业务层内部恢复的内容 解决方案是简单地将“initialize”标记为非事务性,并将这些内容放入一个单独的方法中,该方法为每次尝试启动一个新事务
编辑:我的答案仅适用于您实际设法在catch块中捕获异常的情况,如果您没有,则意味着您只是在提交过程中获取异常,在这种情况下,上述解决方案也适用。这是我选择的一种适合我的解决方案。而不是注入PersistenceContext:
@PersistenceContext
private EntityManager em;
我正在注入一个数据源资源:
@Resource(lookup = "jdbc/sloocefw")
private DataSource dataSource;
这使我能够创建自己的SQL语句(这一点很重要),使我能够在尝试插入具有重复键的行时捕获SQLException
public void initialize() {
try (Connection connection = dataSource.getConnection()) {
PreparedStatement ps = connection.prepareStatement("INSERT INTO user (id, firstName, lastName) VALUES (" + id + ", 'John', 'Doe')");
ps.executeUpdate();
} catch(SQLException e) {
e.printStackTrace();
}
}
我现有的用户实体bean管理id(自动递增)。我需要更改为手动管理(如上面的示例中所示)或使用数据库自动增量
我更愿意使用实体bean,但当我使用实体bean尝试插入重复键时,会导致无法捕获的系统异常。为了捕获
PSQLException
或任何其他与数据库相关的异常,需要手动刷新实体管理器。否则,您的更改将在方法完成后(提交期间)刷新,因此您无法捕获它。若系统异常离开EJB,那个么它将被销毁,事务将回滚。谢谢Geinmachi,但对我来说它并没有任何改变。下面的代码仍然回滚事务try{User User User=new User(0,“John”,“Doe”);em.persist(User);em.flush();}catch(异常e){e.printStackTrace();}
PSQLException
是系统异常,而不是应用程序异常,因此将其添加到
中没有意义。了解更多关于EJB.Geinmachi的信息,还有其他建议吗?我已经更新了这个问题。非常感谢。这个解决方案是可行的,也是我正在寻找的。@ NHO JoToM,它的答案是有用的,请考虑把它标记为正确的ANWSER。我更新了这个问题。此解决方案不起作用,因为PSQLException看起来像是无法捕获的SystemException。还有其他想法吗?