在 JBoss AS 7 中捕获 PersistenceException 或 ConstraintViolationException

发布于 2024-12-24 18:21:27 字数 1959 浏览 2 评论 0原文

我正处于从 JBoss AS 6 到 JBoss AS 7 的迁移过程中,但我的测试遇到了问题。让我们假设一个简单的实体 EJB:

@Entity public class MyTest implements Serializable
{
  @Id @GeneratedValue(strategy=GenerationType.AUTO)
  private long id;

  @NotNull
  private String headline;
}  //getter/setter

在我的 @Stateless Bean 中,我正在做类似的事情(就像之前使用 JBoss5 和 JBoss6 一样):

@Inject private EntityManager em;

public <T extends Object> T persist(T o) throws MyContraintViolationException
{
    System.out.println("***************** persist:");
    try
    {
      em.persist(o);
    }
    catch (Exception e)
    {
      System.out.println("*************** exception:");
      // Further investigation of Exception e,
      // then throw MyContraintViolationException
    }
}

如果我不违反 @NotNull ,这就可以正常工作约束。如果 headline==null,我会收到异常,但进入我的 catch 块:

12:19:45 INFO  ******************** persist:
12:19:45 WARN  [com.arjuna.ats.arjuna] (management-handler-threads - 2)
   ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for
   SynchronizationImple< 0:ffffc0a801fb:4f969a6e:4f058744:9,
   org.hibernate.engine.transaction.synchronization.internal.
   RegisteredSynchronization@38eb9b73 >: javax.persistence.PersistenceException:
   error during managed flush
...
Caused by: javax.validation.ConstraintViolationException: Validation failed for
   classes [my.test.MyTest] during persist time for groups
   [javax.validation.groups.Default, ] List of constraint violations:[
   ConstraintViolationImpl{interpolatedMessage='kann nicht null sein',
   propertyPath=headline, rootBeanClass=class my.test.MyTest,
   messageTemplate='{javax.validation.constraints.NotNull.message}'}

我很高兴看到错误消息比以前版本的 JBoss 详细得多,但我如何捕获 javax.validation.ConstraintViolationException 并抛出我自己的 MyContraintViolationException?甚至连调试消息*****异常没有被打印出来。

I'm in the migration process from JBoss AS 6 to JBoss AS 7 and have trouble with my tests. Let's assume a simple entity EJB:

@Entity public class MyTest implements Serializable
{
  @Id @GeneratedValue(strategy=GenerationType.AUTO)
  private long id;

  @NotNull
  private String headline;
}  //getter/setter

In my @Stateless Bean I'm doing something like this (like before with JBoss5 and JBoss6):

@Inject private EntityManager em;

public <T extends Object> T persist(T o) throws MyContraintViolationException
{
    System.out.println("***************** persist:");
    try
    {
      em.persist(o);
    }
    catch (Exception e)
    {
      System.out.println("*************** exception:");
      // Further investigation of Exception e,
      // then throw MyContraintViolationException
    }
}

This works fine if I don't violate the @NotNull constraint. If headline==null, I get exceptions, but don't enter my catch block:

12:19:45 INFO  ******************** persist:
12:19:45 WARN  [com.arjuna.ats.arjuna] (management-handler-threads - 2)
   ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for
   SynchronizationImple< 0:ffffc0a801fb:4f969a6e:4f058744:9,
   org.hibernate.engine.transaction.synchronization.internal.
   RegisteredSynchronization@38eb9b73 >: javax.persistence.PersistenceException:
   error during managed flush
...
Caused by: javax.validation.ConstraintViolationException: Validation failed for
   classes [my.test.MyTest] during persist time for groups
   [javax.validation.groups.Default, ] List of constraint violations:[
   ConstraintViolationImpl{interpolatedMessage='kann nicht null sein',
   propertyPath=headline, rootBeanClass=class my.test.MyTest,
   messageTemplate='{javax.validation.constraints.NotNull.message}'}

I'm happy to see that the error message is much more detailed than in previous versions of JBoss, but how can I catch a javax.validation.ConstraintViolationException and throw my own MyContraintViolationException? Even the debug message ***** exception is not printed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不羁少年 2024-12-31 18:21:28

您正在使用 EJB 来包含您的entityManager。对无状态 EJB 的每个方法调用都包装在事务中。

您已注入 EntityManager。这意味着 EntityManager 也将成为您事务的一部分。 EntityManager 仅在事务提交期间刷新,这就是您不会看到此错误消息的原因。

您应该执行以下操作:

@Inject private EntityManager em;

public <T extends Object> T persist(T o) throws MyContraintViolationException
{
System.out.println("***************** persist:");
em.persist(o);
try
{
   em.flush();
}
catch (Exception e)
{
  System.out.println("*************** exception:");
  // Further investigation of Exception e,
  // then throw MyContraintViolationException
}
}

You are using an EJB to contain your entityManager. Every method call to a Stateless EJB is wrapped in a transaction.

You have injected the EntityManager. This means that the EntityManager will be part of your transaction as well. The entityManager is only flushed during transaction commit, which is why you will not be seeing this error message.

What you should do is the following:

@Inject private EntityManager em;

public <T extends Object> T persist(T o) throws MyContraintViolationException
{
System.out.println("***************** persist:");
em.persist(o);
try
{
   em.flush();
}
catch (Exception e)
{
  System.out.println("*************** exception:");
  // Further investigation of Exception e,
  // then throw MyContraintViolationException
}
}
甜警司 2024-12-31 18:21:27

如果您阅读消息和异常的堆栈跟踪,您将看到此异常不是由调用 persist 引发的,而是由刷新引发的:

托管刷新期间出错

持久期间发生错误不会发出任何查询,也不会将任何内容保存到数据库。它只是要求实体管理器使临时实体持久化。在刷新时(即在事务提交之前,或者在 Hibernate 执行可能需要该实体位于数据库中才能返回正确结果的查询之前,或者显式调用 flush() 时) ,然后检查约束并执行插入查询。

您可以显式调用刷新,但它会因为不允许 Hibernate 批处理多个查询并仅在必要时执行它们而影响应用程序的性能。我只会使用本机异常。为什么需要这样的转换?

If you read the message and the stack trace of the exception, you'll see that this exception is not thrown by the call to persist, but by the flush:

error during managed flush

persist doesn't issue any query and doesn't save anything to database. It just asks the entity manager to make a transient entity persistent. At flush time (i.e. just before the commit of the transaction, or before Hibernate executes a query which might need this entity to be in database to return the correct results, or when flush() is explicitely called), then the constraints are checked and the insert query is executed.

You might call flush explicitely, but it would affect the performance of the application by not letting Hibernate to batch multiple queries and execute them only when necessary. I would just use the native exception. Why do you need such a conversion?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文