11

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

4

1 回答 1

26

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 节)

于 2011-04-04T18:50:05.627 回答