Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在类层次结构中使用注入的EntityManager_Java_Jpa_Jakarta Ee_Ejb 3.0_Jta - Fatal编程技术网

Java 在类层次结构中使用注入的EntityManager

Java 在类层次结构中使用注入的EntityManager,java,jpa,jakarta-ee,ejb-3.0,jta,Java,Jpa,Jakarta Ee,Ejb 3.0,Jta,以下代码起作用: @Stateless @LocalBean public class MyClass { @PersistenceContext(name = "MyPU") EntityManager em; public void myBusinessMethod(MyEntity e) { em.persist(e); } } 但是下面的层次结构在Glassfish 3.0(以及带有Ecl

以下代码起作用:

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


       public void myBusinessMethod(MyEntity e)
       {
          em.persist(e);
       }
 }
但是下面的层次结构在Glassfish 3.0(以及带有EclipseLink的标准JPA注释)的
persist
行中给出了TransactionRequiredException

 @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
和姐妹方法复制到子类中,但我希望将它们放在一个地方

我没有尝试,但这可能是因为我的基类是抽象的,但我想为这样一个(IMHO common)用例学习一个合适的方法

好的,您不能注入到一个超类中,所以您必须注入到实际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;}
} 

更新:我错了,根据JavaEE5平台规范的第5.2.3节,允许在超类字段和方法中进行注入

我更进一步,使用类似的代码GlassFishV3和EclipseLink在我这边做了一个小测试,我无法重现您的问题。因此,我怀疑您的
persistence.xml
存在某种问题。你能提供吗?您使用的是
交易类型=“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>

org.eclipse.persistence.jpa.PersistenceProvider
jdbc/q2484443
假的
顺便说一句,我认为对于简单的数据访问操作,跳过DAO模式是非常好的。看看。

你的方法没有错(如果可行的话)

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

getEntityManager().persist(e);

问题不是使用超类的注入实体管理器,而是调用另一个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
是使用(非JTA)
EntityManagerFactory
的静态方法时,我使用了这个模式。然后我改变了
OtherBean
来扩展
MySuperBean
。我认为,在这种情况下,当
OtherBean
结束
checkAuthority
时,JTA结束事务,
MySuperBean
insert
无法找到要持久化的事务。可以理解,无状态EJB不允许其他EJB继续事务

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


谢谢大家的意见

超类的insert、update和delete做了一些额外的工作,而不仅仅是调用它们,因此我不想在子类中重复我自己。我知道可以通过监听器实现这一点,但我让我的所有实体实现了一个接口,并让它们具有特定的字段。然后,基类可以在insert/update/delete和persist entities中填充这些额外字段。问题不在于持久性,而在于我对EJB事务语义缺乏理解。非常感谢。@Emre正如我所写,您的代码运行良好(至少是您显示的部分)。换句话说,超级类中的注入就是有效的。不要在托管上下文中使用
EntityManagerFactory
,而是使用
EntityManager
注入。