Тайна наследования аннотаций Java EE 6

Я использую наследование с 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 выдаст исключение нулевого указателя при доступе к его диспетчеру сущностей или его построителю критериев (поскольку и @PersistanceContext, и @PostConstruct будут игнорироваться), однако это не так. Может кто-нибудь пояснить, как это на самом деле работает? Я немного беспокоюсь о том, что происходит с моим @TransactionAttributes в суперклассе, могу ли я доверять REQUIRED для фактического использования транзакций при вызове из подкласса, когда подкласс имеет NOT_SUPPORTED в качестве класса по умолчанию?


person Rasmus Franke    schedule 04.04.2011    source источник


Ответы (1)


Аннотации Java не наследуются, но спецификации JavaEE изменяют правила, позволяющие этим атрибутам работать должным образом. См. общие аннотации 1.1 спец. Раздел 2.1 даже использует @TransactionAttribute в качестве примера. Раздел 13.3.7.1 EJB 3.1 также явно устанавливает правила для @TransactionAttribute:

Если у класса компонента есть суперклассы, применяются следующие дополнительные правила.

  • Атрибут транзакции, указанный в суперклассе S, применяется к бизнес-методам, определенным в S. Если атрибут транзакции уровня класса не указан в S, он эквивалентен спецификации TransactionAttribute(REQUIRED) в S.
  • Атрибут транзакции может быть указан в бизнес-методе M, определенном классом S, чтобы переопределить для метода M значение атрибута транзакции, явно или неявно указанное в классе S.
  • Если метод M класса S переопределяет бизнес-метод, определенный суперклассом S, атрибут транзакции M определяется вышеуказанными правилами применительно к классу S.

Короче говоря, для большинства аннотаций JavaEE аннотации уровня метода применяются к этому методу, если подкласс не переопределяет метод, а аннотации уровня класса применяются только ко всем методам, определенным в этом классе. Правило не применяется к определяющим компоненты аннотациям уровня класса, таким как @Stateless (см. раздел 4.9.2.1 спецификации EJB 3.1).

person Brett Kail    schedule 04.04.2011