2011-04-04 53 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)