2012-01-05 100 views
4

我正在从JBoss AS 6迁移到JBoss AS 7,并且遇到了我的测试问题。让我们假设一个简单的实体EJB:JBoss AS 7中的Catch PersistenceException或ConstraintViolationException

@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. 
    [email protected] >: 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也不是已打印。

回答

11

如果你读的消息和异常的堆栈跟踪,你会看到这个异常没有被调用抛出坚持,但冲洗:在

错误管理平齐

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

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

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 
} 
}