我在理解JPA行为时遇到一些麻烦。 Mabye有人可以给我一个暗示。 情况:
产品实体:
@Entity
public class Product implements Serializable {
...
@OneToMany(mappedBy="product", fetch=FetchType.EAGER)
private List<ProductResource> productResources = new ArrayList<ProductResource>();
....
public List<ProductResource> getProductResources() {
return productResources;
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null) return false;
if (!(obj instanceof Product)) return false;
Product p = (Product) obj;
return p.productId == productId;
}
}
资源实体:
@Entity
public class Resource implements Serializable {
...
@OneToMany(mappedBy="resource", fetch=FetchType.EAGER)
private List<ProductResource> productResources = new ArrayList<ProductResource>();
...
public void setProductResource(List<ProductResource> productResource) {
this.productResources = productResource;
}
public List<ProductResource> getProductResources() {
return productResources;
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null) return false;
if (!(obj instanceof Resource)) return false;
Resource r = (Resource) obj;
return (long)resourceId==(long)r.resourceId;
}
}
ProductResource实体: 这是一个具有附加属性(数量)的JoinTable(关联类)。它映射产品和资源。
@Entity
public class ProductResource implements Serializable {
...
@JoinColumn(nullable=false, updatable=false)
@ManyToOne(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
private Product product;
@JoinColumn(nullable=false, updatable=false)
@ManyToOne(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
private Resource resource;
private int amount;
public void setProduct(Product product) {
this.product = product;
if(!product.getProductResources().contains((this))){
product.getProductResources().add(this);
}
}
public Product getProduct() {
return product;
}
public void setResource(Resource resource) {
this.resource = resource;
if(!resource.getProductResources().contains((this))){
resource.getProductResources().add(this);
}
}
public Resource getResource() {
return resource;
}
...
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null) return false;
if (!(obj instanceof ProductResource)) return false;
ProductResource pr = (ProductResource) obj;
return (long)pr.productResourceId == (long)productResourceId;
}
}
这是会话Bean(在glassfish上运行)。
@Stateless(mappedName="PersistenceManager")
public class PersistenceManagerBean implements PersistenceManager {
@PersistenceContext(unitName = "local_mysql")
private EntityManager em;
public Object create(Object entity) {
em.persist(entity);
return entity;
}
public void delete(Object entity) {
em.remove(em.merge(entity));
}
public Object retrieve(Class entityClass, Long id) {
Object entity = em.find(entityClass, id);
return entity;
}
public void update(Object entity) {
em.merge(entity);
}
}
我从java客户端调用会话Bean:
public class Start {
public static void main(String[] args) throws NamingException {
PersistenceManager pm = (PersistenceManager) new InitialContext().lookup("java:global/BackITServer/PersistenceManagerBean");
ProductResource pr = new ProductResource();
Product p = new Product();
Resource r = new Resource();
pr.setProduct(p);
pr.setResource(r);
ProductResource pr_stored = (ProductResource) pm.create(pr);
pm.delete(pr_stored);
Product p_ret = (Product) pm.retrieve(Product.class, pr_stored.getProduct().getProductId());
// prints out true ????????????????????????????????????
System.out.println(p_ret.getProductResources().contains(pr_stored));
}
}
所以这就是我的问题。为什么ProductResource实体仍然在List productResources中(参见上面的代码)。数据库中的productResource元组在删除后消失了,我重新检索了Product实体。如果我理解了客户端的每个方法调用都发生在一个新的持久化上下文中,但是在这里我显然会找回未刷新的产品对象!?
感谢任何帮助
由于
马塞尔
答案 0 :(得分:0)
当我在检索方法中使用refresh方法时,它可以工作。
public Object retrieve(Class entityClass, Long id) {
Object entity = em.find(entityClass, id);
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
em.refresh(entity);
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return entity;
}
所以我假设问题是eclipselink的缓存。如果我在ProductResource对象上使用create方法,则还会存储Product和Resource对象(cascade = CascadeType.Persist)。当我再次加载Product对象时,它会从缓存中出来,因此不是实际的。所以我也应该删除Product和Resource对象列表中的ProductResource对象并进行更新。对?在这个地方调用refresh()并没有多大意义,因为它绕过了缓存。
由于 马塞尔