Поведение JPA - PullRequest
       13

Поведение JPA

0 голосов
/ 16 марта 2010

У меня возникли проблемы с пониманием поведения JPA. Мэйби, кто-то может дать мне подсказку. Ситуация:

Товарная единица:

@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 Entity: Это 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;
}   
}

Это Session Bean (работает на стеклянной рыбе).

@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-клиента:

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 все еще находится в Списке productResources (см. Код выше). Кортеж productResource в БД пропал после удаления, и я вновь получаю сущность Product. Если я правильно понял, каждый вызов метода клиента происходит в новом контексте постоянства, но здесь я, очевидно, возвращаю необновленный объект продукта!?

Любая помощь приветствуется

Спасибо

Marcel

1 Ответ

0 голосов
/ 18 марта 2010

Когда я использую метод обновления в методе получения, он работает.

public Object retrieve(Class entityClass, Long id) {
    Object entity = em.find(entityClass, id);
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    em.refresh(entity);
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    return entity;
}

Итак, я предполагаю, что проблема в кешировании eclipselink. Если я использую метод create для объекта ProductResource, объекты Product и Resource также сохраняются (cascade = CascadeType.Persist). Когда я снова загружаю объект Product, он выходит из кэша и, следовательно, не актуален. Поэтому я должен также просто удалить объект ProductResource в списках объекта Product и Resource и выполнить обновление. Правильно? Вызывать refresh () в этом месте на самом деле не имеет смысла, поскольку он обходит кеширование.

Спасибо Марсель

...