Java EE 6 注解继承之谜 [英] The mystery of Java EE 6 annotations inheritance

查看:36
本文介绍了Java EE 6 注解继承之谜的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一些场景中将继承与 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 在访问其实体管理器或其标准构建器时抛出空指针异常(因为 @PersistanceContext 和 @PostConstruct 都将被忽略),但事实并非如此.有人可以澄清这实际上是如何工作的吗?我有点担心超类中的 @TransactionAttributes 会发生什么,当子类将 NOT_SUPPORTED 作为类默认值时,我可以信任 REQUIRED 从子类调用时实际使用事务吗?

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 定义的业务方法.如果在 S 上未指定类级别的事务属性,则相当于在 S 上指定 TransactionAttribute(REQUIRED).
  • 可以在类 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆