Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.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 未管理find在有状态ejb扩展中找到的JPA实体_Java_Jpa_Ejb_Stateful Session Bean - Fatal编程技术网

Java 未管理find在有状态ejb扩展中找到的JPA实体

Java 未管理find在有状态ejb扩展中找到的JPA实体,java,jpa,ejb,stateful-session-bean,Java,Jpa,Ejb,Stateful Session Bean,我认为em.find找到的实体是由em自动管理的,即使是在事务中,但下面的这个类似乎显示了相反的情况。是我错了还是那节课上的错误是什么 @Stateful @TransactionAttribute(NOT_SUPPORTED) public class CustomerGateway { @PersistenceContext(unitName = "customersPU", type = EXTENDED) private EntityManager em; private

我认为em.find找到的实体是由em自动管理的,即使是在事务中,但下面的这个类似乎显示了相反的情况。是我错了还是那节课上的错误是什么

@Stateful
@TransactionAttribute(NOT_SUPPORTED)
public class CustomerGateway {

  @PersistenceContext(unitName = "customersPU", type = EXTENDED)
  private EntityManager em;
  private Customer customer;

  public Customer find(Long id) {
    // customer is not managed!
    this.customer = em.find(Customer.class, id);
    // Print false!
    System.out.println("Method find: " + em.contains(customer));
    // Print false too (2 is the id of an entity)!
    System.out.println("Method find: " + em.contains(em.find(Customer.class, 2L));
    // A workaround
    customer = em.merge(customer);
    // Print true.
    System.out.println("Method find after merge: " + em.contains(customer));
    return this.customer;
  }
编辑1:实体的代码

@Entity
@NamedQuery(name = "Customer.all", query = "select c from Customer c")
public class Customer implements Serializable {
  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  private String name;

  public Customer() {
  }

  public Customer(String name) {
    this.name = name;
  }

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  @Override
  public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.hashCode() : 0);
    return hash;
  }

  @Override
  public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Customer)) {
      return false;
    }
    Customer other = (Customer) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
      return false;
    }
    return true;
  }

  @Override
  public String toString() {
    return "entity.Customer[ id=" + id + " ]";
  }

}
有状态EJB的代码:

@Stateful
@TransactionAttribute(NOT_SUPPORTED)
public class CustomerGateway {

  @PersistenceContext(type = PersistenceContextType.EXTENDED)
  private EntityManager em;

  private Customer customer;

  public Customer getCustomer() {
    return customer;
  }

  public void create(Customer customer) {
    em.persist(customer);
    this.customer = customer;
  }

  public Customer find(Long id) {
    this.customer = em.find(Customer.class, id);
    System.out.println("customer managed ? " + em.contains(this.customer));
    // Workaround :
//    this.customer = em.merge(customer);
    return customer;
  }

  public void remove(Long id) {
    Customer cust = em.getReference(Customer.class, id);
    em.remove(cust);
  }

  @TransactionAttribute(REQUIRES_NEW)
  public void save() {
  }

  public List<Customer> findAllCustomers() {
    Query query = em.createNamedQuery("Customer.all");
    return query.getResultList();
  }

  @Remove
  public void close() {
  }

}
@Stateful
@TransactionAttribute(不受支持)
公共类CustomerGateway{
@PersistenceContext(类型=PersistenceContextType.EXTENDED)
私人实体管理者;
私人客户;
公共客户getCustomer(){
退货客户;
}
公共作废创建(客户){
em.persist(客户);
this.customer=customer;
}
公共客户查找(长id){
this.customer=em.find(customer.class,id);
System.out.println(“客户管理?”+em.contains(this.customer));
//解决方法:
//this.customer=em.merge(客户);
退货客户;
}
公共无效删除(长id){
Customer cust=em.getReference(Customer.class,id);
em.remove(cust);
}
@TransactionAttribute(需要新的)
公共作废保存(){
}
公共列表findAllCustomers(){
Query Query=em.createNamedQuery(“Customer.all”);
返回query.getResultList();
}
@除去
公众假期结束(){
}
}

我使用NetBeans 7.4、GlassFish 4.0、EJB3.2和Java DB。

您所经历的一切都是根据规范进行的。当事务存在时,持久性上下文保持不变(实体保持连接)。因此,在扩展持久性上下文和不受支持的
事务中,通过调用find方法检索的对象被删除-另外,如果您的
Customer
对象具有惰性关系,并且您试图访问它们,那么很可能会出现运行时异常-

现在,为什么
merge
方法还可以呢?。首先要记住,
merge
返回一个托管实体,并将客户附加到持久性上下文

其次,您有一个
扩展的
持久性上下文,因此,在调用
@Remove
注释方法之前,它不会更新数据库。当此呼叫到达时,您可能会收到一个
TransactionRequiredException

编辑1--------------------------------------------------------------------------------

根据你的评论:

  • find
    不一定要在事务中,不过,如果需要托管对象,则必须有一个

  • 本段是关于EM的生命周期(3.3节),在本例中,试图解释在事务范围bean的方法结束时,实体将被分离,但在扩展EM的情况下,实体将保持连接

  • 有两段很有见地的话:

  • 使用具有扩展持久性上下文的EM时,无论事务是否处于活动状态,都可以调用持久性、移除、合并和刷新操作。当在事务中登记扩展持久性上下文并提交事务时,这些操作的效果将提交到数据库

  • 当有状态会话bean的@Remove方法完成时(或者有状态会话bean实例被销毁),容器关闭持久性上下文

    • 看起来您在问题
      @TransactionAttribute(REQUIRES_NEW)
      中最初省略的方法是成功进行合并的地方。这就是为什么你没有例外
    编辑2--------------------------------------------------------------------------------

    经过一些测试后,GF4出现了一个bug,并已报告>

    编辑3---------------------------------------------------------------------------------


    2014年5月20日:Glassfish 4.0.1的bug被标记为:必须修复。

    根据Checkus的说法,这似乎是GF4中的bug:

    无法告诉您原因,但在前两次调用中必须分离
    客户
    实例。您是否尝试将
    不受支持的
    更改为
    支持的
    必需的
    ,并查看行为是否发生变化?+1回答问题。我在《掌握Java持久性API》一书中找到了以下描述:“find()操作在所有情况下都返回托管实体实例,但在事务范围的实体管理器上的事务外部调用时除外。在这种情况下,实体实例以分离状态返回。”因此,上面的描述似乎与在扩展实体管理器上的事务外部调用find()的类相矛盾。。。或者我们在这里缺少了一些东西(?)@MagicMan:如果我在find方法中添加
    @TransactionAttribute
    ,那么实体就被管理了。但是,根据Wypiperz的说法,即使没有事务,实体也应该被管理。@user1643352您可以发布
    Customer
    entity源代码吗?@CycDemo:您认为什么可以解释find检索到的客户没有被管理?很抱歉,我不知道如何在注释中编写类的代码:-(我认为您错了。这里是JPA规范的摘录:“find方法(假设它是在没有锁的情况下调用的,或者是使用LockModeType.NONE调用的)不需要在事务上下文中调用getReference方法。如果使用具有事务作用域持久性上下文的实体管理器,则将分离生成的实体;如果使用具有扩展持久性上下文的实体管理器,则将对其进行管理“。持久性上下文是扩展的,所以应该管理客户;这就是我将其扩展的原因。对于您答案的第二部分:有状态EJB有另一个用@TransactionAttribute(需要新的)注释的方法,当我调用该方法时将发生更新。它与我的问题无关,所以我没有编写