在JBoss AS 7中捕获PersistenceException或ConstraintViolationException

时间:2012-01-05 11:49:26

标签: persistence ejb jpa-2.0 entitymanager jboss7.x

我正处于从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?甚至调试消息***** exception打印。

2 个答案:

答案 0 :(得分:11)

如果您阅读了异常的消息和堆栈跟踪,您将看到对persist的调用不会抛出此异常,而是通过flush:

  托管刷新期间

错误

persist不会发出任何查询,也不会向数据库保存任何内容。它只是要求实体管理器使瞬态实体持久化。在刷新时(即在提交事务之前,或者在Hibernate执行可能需要此实体在数据库中以返回正确结果的查询之前,或者在明确调用flush()时),则约束为检查并执行插入查询。

你可能会明确地调用flush,但它会影响应用程序的性能,不要让Hibernate批处理多个查询并仅在必要时执行它们。我只会使用本机异常。你为什么需要这样的转换?

答案 1 :(得分:0)

您正在使用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
}
}