在状态EJB扩展中找到的JPA实体无法管理



我认为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() {
  }
}

我与Netbeans 7.4,Glassfish 4.0,EJB 3.2,Java db。

您所经历的一切都是根据规格。交易存在时,持久性上下文仍然存在(并且实体持续存在)。因此,在扩展持久性上下文和NOT_SUPPORTED事务中,通过调用查找方法检索的对象被驱动。 - 此外,如果您的Customer对象具有懒惰的关系,并且您尝试访问它们,那么您很可能会得到运行时例外。-

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

第二,您具有EXTENDED持久性上下文,因此,它不会更新数据库,直到您调用@Remove注释方法为止。当此通话到达时,您可能会得到TransactionRequiredException

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

根据您的评论:

  • find不需要进行交易,尽管如果您想要托管对象,则必须有一个。

  • 段落是关于EM生命周期(3.3部分)的,在这种情况下,试图解释说,在交易量的豆类方法的结尾处,实体将被脱离,但是,在扩展的EM案例将仍然附加。

  • 有2个有见地的段落:

  1. 使用具有扩展持久性上下文的EM时,无论交易是否处于活动状态,都可以称为持久,删除,合并和刷新操作。当交易中征集扩展的持久性上下文并进行交易时,这些操作的效果将归于数据库。

  2. 当状态会话的@remove方法bean完成时,持久性上下文是由容器关闭的(或者是状态会话bean实例被销毁)。

  • 看起来您最初用@TransactionAttribute(REQUIRES_NEW)省略的方法是合并成功发生的地方。这就是为什么你没有例外。

编辑2 --------------------------------------------------------------------------------------------------------------------------------------

经过一番测试,GF4有一个错误,已报告&gt;https://java.net/jira/browse/glassfish-20968

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

20/5月/2014年:该错误已被标记为:必须修复 for Glassfish 4.0.1。

根据checkus,它似乎是gf4中的错误:

最新更新