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
Jpa 使用扩展PersistentContext时,实体处于非托管状态_Jpa_Jakarta Ee_Persistence - Fatal编程技术网

Jpa 使用扩展PersistentContext时,实体处于非托管状态

Jpa 使用扩展PersistentContext时,实体处于非托管状态,jpa,jakarta-ee,persistence,Jpa,Jakarta Ee,Persistence,环境: JDK 1.8 WildFly 10.0.0.Final 我有以下@statefulbean @Stateful @SessionScoped @Local(CdiStatefulEmployeeService.class) public class CdiStatefulEmployeeBean implements CdiStatefulEmployeeService { @PersistenceContext(name = "employees", type = P

环境:

  JDK 1.8
  WildFly 10.0.0.Final
我有以下@statefulbean

@Stateful
@SessionScoped
@Local(CdiStatefulEmployeeService.class)
public class CdiStatefulEmployeeBean implements CdiStatefulEmployeeService {

  @PersistenceContext(name = "employees", type = PersistenceContextType.EXTENDED)
  EntityManager extendedEm;

  private Employee cached;

  @Override
  public String service() {
    cached = extendedEm.find(Employee.class, 499983);
    return cached.getFirstName();
  }

  @Override
  public String updateEntity() {
    cached.setFirstName("Uri2");
    //extendedEm.flush();   -- Line 1
    return cached.getFirstName();
  }
}
和下面的Servlet客户端

@WebServlet("/atInjectedStatefulEjbClient")
public class AtInjectedStatefulEjbClient extends HttpServlet {

  @Inject
  CdiStatefulEmployeeService statefulBean;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    HttpSession session = req.getSession(true);
    resp.setContentType("text/plain");

    PrintWriter pw = resp.getWriter();

    pw.println(statefulBean.service());
    pw.println();
    pw.println(statefulBean.updateEntity());

    session.invalidate();
    pw.flush();
    pw.close();
  }
}
观察:调用bean.updateEntity()方法不会自动保存更改,即将名字设置为“Uri2”

问题:在扩展持久性上下文的情况下,实体不是跨调用进行管理吗

调用flush()。基本上,在updateEntity()调用中不管理实体。我觉得这很奇怪。有什么想法吗

更新: 为了排除这种可能性,尝试使用相同的代码,但使用以下代码

  • 无@SessionScoped
  • 否@Inject(替换为servlet doGet()内的JDNI查找)
  • 在bean中添加了@Remove方法
  • 调用其他2个方法后,让servlet doGet()调用@Remove
结果:同样的问题。第一次服务调用后未管理实体


Rakesh

假设在
updateTity
显示所描述的行为之前调用了
service
方法:默认为
service
方法的事务属性,这意味着,正如您在对
updateTity
的评论中指出的,事务在
service
调用结束时提交。此提交使缓存的
实体处于非托管状态。我建议用
@TransactionAttribute(TransactionAttributeType.NOT_受支持)
注释
服务
方法,该方法应保持
缓存
实体管理,随后调用
更新属性
查找托管实体


通常,在扩展持久性上下文中,FacadeEJB类用
@TransactionaAttribute(TransactionaAttribute.NOT_SUPPORTED)
注释,并且只有应该提交的EJB方法才能获得不同的事务属性(参见示例文章)。

从不将有状态(依赖于会话的)bean注入servlet(由多个用户使用=由多个会话使用)。如果使用CMT,事务的提交将在调用@Remove-marked方法后执行。它在哪里?它可以为空,但在有状态bean中是关键的

但这将是一个可行的解决方案:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
  <h:head>
    <title>Facelet Title</title>
  </h:head>
  <h:body>
    <h:form>
    <h:inputText value="#{employeeMB.emplyeeName}"/>
    <h:commandButton value="Submit" action="#{employeeMB.onSubmit}"/>
    </h:form>
  </h:body>
</html>

@ManagedBean
@SessionScoped
@Getter
@Setter
public class EmployeeMB
{
  private String employeeName;

  @EJB
  private EmployeeSB employeeSB;

  public void onSubmit()
  {
    employeeSB.persist( employeeName );
    employeeName = "";
  }
}

@Stateless
@LocalBean
public class EmployeeSB
{
  @PersistenceContext
  private EntityManager em;

  public void persist( String employeeName_ )
  {
    Employee e = new Employee();
    e.setName( employeeName_ );
    em.persist( e );
  }
}

Facelet标题
@ManagedBean
@会议范围
@吸气剂
@塞特
公共类雇员b
{
私有字符串employeeName;
@EJB
私人雇员b雇员b;
提交时公共无效()
{
雇员某人坚持(雇员姓名);
employeeName=“”;
}
}
@无国籍
@本地豆
公共阶层雇员b
{
@持久上下文
私人实体管理者;
public void persist(字符串employeeName)
{
员工e=新员工();
e、 设置名称(员工名称);
em.e;
}
}

似乎是WildFly中的一个bug。所有文档(规范、书籍等)都指出,扩展上下文意味着在事务结束时防止实体分离


归档的Wildfly问题:

我不同意。updateEntity()方法位于具有默认事务策略的EJB内部。如果emp.setFirstName()是在servlet类中调用的,那么我同意它不会持久化更改。但这里不是这样。默认情况下,TransactionAttributeType是必需的,所以您应该将您的更改保存在数据库中。您不是在某个地方覆盖了此行为吗?这也是我的期望,即自动保存到DB的更改。不是。不是ransaction属性完全改变。嗯,从逻辑上讲,这听起来不正确。原因:规范明确说明扩展实体管理器跨越多个事务。此外,规范也有类似的示例。也就是说,谁和如何划分事务并不重要。尽管如此,还是尝试了一下,结果是一样的,即。实体没有更新。它只是测试代码,这就是我这样做的原因。如果你在OP中看到我的下一次更新,我已经将其切换到JNDI查找以排除奇怪的行为。回到你的建议,我发现奇怪的是,有状态事务只在调用@Remove时提交。这难道不意味着有状态bean不遵守tr吗反作用边界?