3

以下代码有效:

@Stateless
@LocalBean
public class MyClass 
{
       @PersistenceContext(name = "MyPU")
       EntityManager em;


       public void myBusinessMethod(MyEntity e)
       {
          em.persist(e);
       }
 }

但是以下层次结构在 Glassfish 3.0 中(以及带有 EclipseLink 的标准 JPA 注释)中的persist.

 @Stateless
 @LocalBean
public class MyClass extends MyBaseClass
{
       public void myBusinessMethod(MyEntity e)
       {
          super.update(e);
       }
 }



public abstract class MyBaseClass
{
       @PersistenceContext(name = "MyPU")
       EntityManager em;

       public void update(Object e)
       {
          em.persist(e);
       }
 }   

对于我的 EJB,我在一个抽象类中收集了通用代码,以获取更简洁的代码。(update还保存了谁做了操作以及何时,我所有的实体都实现了一个接口。)

这个问题不是致命的,我可以简单地将方法复制update和姐妹方法到子类,但我想将它们全部放在一个地方。

我没有尝试,但这可能是因为我的基类是抽象的,但我想为这种(恕我直言常见)用例学习一个合适的方法。

4

3 回答 3

1

AFAIK,您不能注入超类,因此您必须注入实际 EJB 的字段或方法。你可以这样做:

public class MyBaseEJB {
   public abstract EntityManager getEM();

   public void update(Object e) {
       getEM().persist(e);
   }

}

@Stateless
public class MyEJB extends MyBaseEJB {
   @PersistenceContext
   EntityManager em;

   public EntityManager getEM() { return em;}
} 

更新:我错了,根据 Java EE 5 平台规范的第 5.2.3 节,超类字段和方法中允许注入。

我更进一步,使用类似的代码、GlassFish v3 和 EclipseLink 在我这边做了一个小测试,但我无法重现您的问题。所以我怀疑你的persistence.xml. 你能提供吗?你在用transaction-type="JTA"吗?以防万一,这是我使用的一个:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_2_0.xsd" version="2.0">
  <persistence-unit name="MyPU" transaction-type="JTA">
    <!-- EclipseLink -->
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/q2484443</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
      <property name="eclipselink.ddl-generation.output-mode" value="database"/>
    </properties>
  </persistence-unit>
</persistence>

顺便说一句,我认为跳过 DAO 模式进行简单的数据访问操作是完全可以的。看看这个先前的答案

于 2010-03-20T19:40:28.417 回答
0

您的方法没有错(如果有效)

然而,更常见的是使用(注入)一个 Dao 并在其上调用方法,或者如果 Dao 是仅包装 的冗余层EntityManager,您可以直接调用方法EntityManager。当然,EntityManager通过受保护的 getter 将 暴露给子类。

getEntityManager().persist(e);
于 2010-03-20T19:41:13.253 回答
0

问题不是使用超类的注入实体管理器,而是调用另一个 EJB 的方法:例如

@Stateless
@LocalBean
public class MyBean extends MySuperBean
{
  @EJB
  com.example.project.MyOtherBean otherBean;

  public boolean myService(String userName, MyEntity entity)
  {
     if(otherBean.checkAuthority(userName))
     { 
        super.insert(entity);
     }
   }
 }

我在OtherBean不是 bean 并且checkAuthority是使用 (non-JTA) 的静态方法时使用这种模式EntityManagerFactory。然后我也改变OtherBean了扩展MySuperBean。我认为,在这种情况下,当OtherBean结束时checkAuthority,JTA 结束事务并且找不到事务来持久化实体MySuperBeaninsert可以理解的是,无状态 EJB 不允许其他 EJB 进行事务处理。

作为Pascal,我最初认为注入不适用于继承,但是当我直接em.persist()在子类中调用时,这个问题仍然存在。在此之后,我终于能够检查其他可能的原因。

感谢所有的投入。

于 2010-03-20T22:43:23.430 回答