我在几个方案中使用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会发生什么情况,当子类具有NOT_SUPPORTED作为类默认值时,可以信任一个required实际使用从子类调用的事务吗?
解决方法
Java注释不被继承,但JavaEE规范更改了规则,以允许这些属性按预期工作.参见常见的注释1.1规范. 2.1节甚至以@TransactionAttribute为例. EJB 3.1第13.3.7.1节还明确说明了@TransactionAttribute的规则:
If the bean class has superclasses,the following additional rules apply.
- transaction attribute specified on a superclass S applies to the business methods defined by S. If a class-level transaction attribute is not specified on S,it is equivalent to specification of TransactionAttribute(required) on S.
- A transaction attribute may be specified on a business method M defined by class S to override for method M the transaction attribute value explicitly or implicitly specified on the class S.
- If a method M of class S overrides a business method defined by a superclass of S,the transaction attribute of M is determined by the above rules as applied to class S.
简而言之,对于大多数JavaEE注释,方法级注释适用于该方法,除非子类覆盖该方法,而类级注解仅适用于该类中定义的所有方法.该规则不适用于“组件定义”类级别注释,例如@Stateless(请参阅EJB 3.1规范第4.9.2.1节)