2011-04-04 12 views
10

estoy usando la herencia con EJB en algunos escenarios, a veces con anotaciones en la superclase como esto entityDAO genérica:El misterio de la herencia de Java EE 6 anotaciones

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); 
    } 

} 

Con un ejemplo subclase implementado como esto:

@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; 
     } 
    } 
} 

Hace poco leí que las anotaciones Java no se heredan (source). Esto debería causar que mi JpaDAO arroje una excepción de puntero nulo al acceder a su administrador de entidades o su generador de criterios (ya que se ignorarían tanto @PersistanceContext como @PostConstruct), sin embargo, este no es el caso. ¿Alguien puede aclarar cómo funciona esto realmente? Estoy un poco preocupado por lo que sucede con mis @TransactionAttributes en la superclase, ¿puedo confiar en un REQUERIDO para usar realmente las transacciones cuando se me llama desde la subclase, cuando la subclase NO tiene NOT_SUPPORTED como clase predeterminada?

Respuesta

21

Las anotaciones Java no se heredan, pero las especificaciones JavaEE cambian las reglas para permitir que estos atributos funcionen como se esperaba. Ver las anotaciones comunes 1.1 especificaciones. La Sección 2.1 incluso usa @TransactionAttribute como ejemplo. EJB 3.1 sección 13.3.7.1 también establece explícitamente las reglas para @TransactionAttribute:

Si la clase de bean tiene superclases, se aplican las siguientes reglas adicionales.

  • atributo de transacción especificado en una superclase S se aplica a los métodos de negocio definidas por S. Si un atributo de transacción de nivel de clase no se especifica en S, es equivalente a la especificación de TransactionAttribute (REQUERIDO) en S.
  • Se puede especificar un atributo de transacción en un método comercial M definido por clase S para anular el método M el valor de atributo de transacción explícita o implícitamente especificado en la clase S.
  • Si un método M de clase S anula un método comercial definido por una superclase de S, el atributo de transacción de M está determinado por las reglas anteriores según se aplica a la clase S.

En resumen, para la mayoría de las anotaciones JavaEE, las anotaciones de nivel método se aplican a este método a menos que una subclase reemplaza el método, y las anotaciones de nivel de clase se aplican a todos los métodos definidos en solamente esa clase. La regla no se aplica a las anotaciones de nivel de clase "que definen componentes", como @Stateless (consulte la sección especificación EJB 3.1 4.9.2.1)