【问题标题】:The mystery of Java EE 6 annotations inheritanceJava EE 6 注解继承之谜
【发布时间】:2011-07-29 00:56:21
【问题描述】:

我在一些场景中使用 EJB 继承,有时在超类中使用注释,例如这个通用 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);
    }

}

使用这样实现的示例子类:

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

【问题讨论】:

    标签: inheritance annotations jpa-2.0 java-ee-6 ejb-3.1


    【解决方案1】:

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

    如果 bean 类具有超类,则适用以下附加规则。

    • 在超类S上指定的事务属性适用于由S定义的业务方法。如果在S上没有指定类级事务属性,则相当于在S上指定TransactionAttribute(REQUIRED)。
    • 可以在由类 S 定义的业务方法 M 上指定事务属性,以便为方法 M 覆盖在类 S 上显式或隐式指定的事务属性值。
    • 如果类 S 的方法 M 覆盖由 S 的超类定义的业务方法,则 M 的事务属性由应用于类 S 的上述规则确定。

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

    【讨论】:

      猜你喜欢
      • 2017-03-20
      • 1970-01-01
      • 1970-01-01
      • 2016-11-11
      • 1970-01-01
      • 2011-11-02
      • 2015-08-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多