2011-04-04 84 views
10

我使用的继承与EJB在少数情况下,有时在这样的通用entityDAO超类的注解奥秘:Java EE 6个的注解继承

public class JpaDAO<T>{ 
    protected Class<T> entityClass; 

    @PersistenceContext(unitName="CarrierPortalPU") 
    protected EntityManager em; 
    protected CriteriaBuilder cb; 

    @PostConstruct 
    private void init() { 
     cb = em.getCriteriaBuilder(); 
    } 

    public JpaDAO(Class<T> type) { 
     entityClass = type; 
    } 

    @TransactionAttribute(TransactionAttributeType.REQUIRED) 
    public void create(T entity) { 
     em.persist(entity); 
    } 

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
    public T find(Object id) { 
     return em.find(entityClass, id); 
    } 

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
    public List<T> findAll(){ 
     CriteriaQuery<T> cq = cb.createQuery(entityClass); 
     Root<T> entity = cq.from(entityClass); 
     cq.select(entity); 
     return em.createQuery(cq).getResultList(); 
    } 

    @TransactionAttribute(TransactionAttributeType.REQUIRED) 
    public void remove(T entity) { 
     em.remove(em.merge(entity)); 
    } 

    @TransactionAttribute(TransactionAttributeType.REQUIRED) 
    public T edit(T entity) { 
     return em.merge(entity); 
    } 

} 

像这样实施的示例子类:

@Stateless 
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
public class DepartmentDAO extends JpaDAO<Department> { 

    public DepartmentDAO() { 
     super(Department.class); 
    } 

    public Department findByName(String name){ 
     CriteriaQuery<Department> cq = cb.createQuery(Department.class); 
     Root<Department> department = cq.from(Department.class); 
     cq.where(cb.equal(department.get(Department_.name), name)); 
     cq.select(department); 
     try{ 
      return em.createQuery(cq).getSingleResult(); 
     }catch(Exception e){ 
      return null; 
     } 
    } 
} 

我最近读到,Java注释不是继承(source)。这应该会导致我的JpaDAO在访问其实体管理器或其标准构建器时抛出空指针异常(因为@PersistanceContext和@PostConstruct都将被忽略),但事实并非如此。有人可以澄清这是如何工作的吗?我高调担心超类中的@TransactionAttributes发生了什么,如果子类的NOT_SUPPORTED为类的默认值,我可以信任REQUIRED实际使用从子类调用的事务吗?

回答

21

Java注释并未继承,但JavaEE规范更改规则以允许这些属性按预期工作。请参阅常见注释1.1规范。 2.1节甚至使用@TransactionAttribute作为例子。 EJB 3.1第13.3.7.1节还明确规定了@TransactionAttribute的规则:

如果bean类具有超类,则应用以下附加规则。上的超类S]指定

  • 事务属性适用于由S.定义的业务的方法。如果在S未指定类级事务属性,它相当于TransactionAttribute(REQUIRED)的规范上S.
  • 可以在由类S定义的业务方法M上指定事务属性,以针对方法M覆盖在类S上显式或隐式指定的事务属性值。
  • 如果类S的方法M覆盖由类S定义的业务方法S的超类,M的交易属性由上述规则确定为适用于S类。

简而言之,对于大多数JavaEE批注,方法级批注适用于该方法,除非子类重写该方法,并且类级批注仅适用于该类中定义的所有方法。该规则不适用于“组件定义”类级别注释,如@Stateless(请参阅EJB 3.1规范部分4.9.2.1)