Java EE 6的注解继承的奥秘 [英] The mystery of Java EE 6 annotations inheritance
问题描述
我使用的继承与EJB在少数情况下,有时在超类的注解这样的通用entityDAO:
I'm using inheritance with EJB in a few scenarios, sometimes with annotations in the super class like this generic entityDAO:
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);
}
}
通过这样实现的例子子类:
With an example subclass implemented like this:
@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注解是不能继承(源)。这应该引起我的JpaDAO访问它的EntityManager或其criteriabuilder(因为这两个@PersistanceContext和@PostConstruct会被忽略)时,抛出一个空指针异常,然而,这又何尝不是如此。有人可以澄清如何真正起作用?我升技担心什么超碰巧我@TransactionAttributes,我可以信任所需的实际使用交易从子类时,子类已NOT_SUPPORTED作为类的默认调用的时候?
I recently read that java annotations are NOT inherited (source). This should cause my JpaDAO to throw a null pointer exception when accessing its entitymanager or its criteriabuilder (since both @PersistanceContext and @PostConstruct would be ignored), however this it not the case. Can someone clarify how this really works? I am abit worried about what happens to my @TransactionAttributes in the superclass, can I trust a REQUIRED to actually use transactions when called from the subclass, when the subclass has NOT_SUPPORTED as class default?
推荐答案
Java注解是不能继承,但JavaEE的规格改变规则,让这些属性来达到预期效果。请参见常见注解1.1规范。 2.1节甚至使用@TransactionAttribute作为一个例子。 EJB 3.1节13.3.7.1也明确规定的规则@TransactionAttribute:
Java annotations are not inherited, but the JavaEE specs change the rules to allow these attributes to work as expected. See the common annotations 1.1 spec. Section 2.1 even uses @TransactionAttribute as an example. EJB 3.1 section 13.3.7.1 also explicitly states the rules for @TransactionAttribute:
如果bean类具有超类,下面的附加规则。
If the bean class has superclasses, the following additional rules apply.
- 在一个超类S]指定的事务属性适用于如果不是指定一个类级别的事务属性由S.定义的业务方法,它相当于TransactionAttribute(必填)对S规范。
- 的事务属性可以通过S类定义的业务方法M.指定覆盖法M上的事务属性值或明或暗地在S级指定。
- 如果S类的方法M.覆盖由S的超类中定义的业务方法,M的交易属性按上述规则确定的适用于S级。
总之,对于大多数的JavaEE注释,方法级别的注解适用于该方法,除非子类覆盖的方法和类级别的注解适用于只类中定义的所有方法。该规则并不适用于定义组件类级别的注解,如@Stateless(见EJB 3.1规范第4.9.2.1)
In short, for most JavaEE annotations, method-level annotations apply to that method unless a subclass overrides the method, and class-level annotations apply to all methods defined in that class only. The rule does not apply to "component-defining" class-level annotations, such as @Stateless (see the EJB 3.1 specification section 4.9.2.1)
这篇关于Java EE 6的注解继承的奥秘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!