简体   繁体   中英

Java Hibernate JPA Deleting OneToMany Relation And MapKeyJoinColumn Relation Object

I want to create and delete one of ProductPrice , update is working properly but others gives exception

PRODUCT CLASS

public class Product extends GenericEntity {
    @OneToMany(fetch=FetchType.EAGER, mappedBy = "product", targetEntity = ProductPrice.class, cascade = {CascadeType.ALL}, orphanRemoval=true)
    @Fetch(FetchMode.SUBSELECT)    
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="ncStandardElements")
    private List<ProductPrice> productPrices = new ArrayList<ProductPrice>();

    @OneToMany(fetch=FetchType.EAGER, mappedBy = "product", targetEntity = ProductPrice.class)
    @Fetch(FetchMode.SUBSELECT)    
    @MapKeyJoinColumn(name="CURRENCY_ID")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region="ncStandardElements")
    private Map<Currency, ProductPrice> productPriceMap = new HashMap<Currency, ProductPrice>();
}

PRODUCTPRICE CLASS

public class ProductPrice extends GenericEntitySimple {

    @ManyToOne(targetEntity = Product.class, optional=false)
    @JoinColumn(name = "PRODUCT_ID", referencedColumnName = "ID")
    private Product product;
}




public void removeProductPrice(ProductPrice price){
    Product p = price.getProduct();
    //Map<Currency, ProductPrice> productPriceMap = p.getProductPriceMap();
    //productPriceMap.remove(price);

    List<ProductPrice> prices = p.getProductPrices();
    prices.remove(price);
    p.setProductPrices(prices);
    productDao.merge(p);
}

If price is created on same session, delete operation is successful, however, if it has created before present session, it throws this error :

Jun 13, 2013 3:26:29 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet appServlet threw exception
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.netasoft.commerce.framework.catalog.model.ProductPrice#220]
    at org.hibernate.impl.SessionFactoryImpl$2.handleEntityNotFound(SessionFactoryImpl.java:435)
    at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:233)
    at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285)
    at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
    at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1090)

I dont get MapKeyJoinColumn completely, and I cannot find documentation about this situation. I think Map lists cache cause this error. Any well prepared documentation suggestions is approved, also.

I am assuming that before calling the removeProductPrice() you open a session and begin a transaction.

In the removeProductPrice() method load the productPrice object to persistence context by doing a get(). Like,

ProductPrice price = productPriceDao.get(price.getPriceId());

// Then your logic to delete.

I suspect that the passed ProductPrice object to the removeProductPrice() method is not present in the persistence context of the session.

Can you post the full stack trace which shows the exact line which is causing the exception .

The last solution I have found is that;

The real problem is same object is in two different list cache. So, when you changed one of them, it cause error according to FetchType method you choose.

If you define FetchTypes as FetchType.Eager , FetchType.SUBSELECT and CacheConcurrencyStrategy.READ_WRITE , you can easily crud by changing objects in two side of cache! ie you want to delete one of price, you should remove it from productPriceMap & productPrices too. Then merge product; and it has finished!

    @OneToMany(fetch=FetchType.EAGER, mappedBy = "product", targetEntity = ProductPrice.class, cascade = {CascadeType.ALL}, orphanRemoval=true)
    @Fetch(FetchMode.SUBSELECT)    
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="ncStandardElements")
    private List<ProductPrice> productPrices = new ArrayList<ProductPrice>();

    @OneToMany(fetch=FetchType.EAGER, mappedBy = "product", targetEntity = ProductPrice.class)
    @Fetch(FetchMode.SUBSELECT)    
    @MapKeyJoinColumn(name="CURRENCY_ID")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="ncStandardElements")
    private Map<Currency, ProductPrice> productPriceMap = new HashMap<Currency, ProductPrice>();

CRUD ON SERVICE

public void removeProductPrice(ProductPrice price){
    Product p = price.getProduct();
    Map<Currency, ProductPrice> productPriceMap = p.getProductPriceMap();
    productPriceMap.remove(price);

    List<ProductPrice> prices = p.getProductPrices();
    prices.remove(price);
    p.setProductPrices(prices);

    p.removeProductPriceMap(price);

    productDao.merge(p);
}

public void saveProductPrice(ProductPrice price, boolean isNew){
    Product p = price.getProduct();
    List<ProductPrice> prices = p.getProductPrices();
    if(isNew ){
        prices.add(price);
    }
    else{
        int i = 0;
        for (ProductPrice tp: prices){
            if (tp.getId() == price.getId()){
                prices.set(i, price);
                break;
            }
            i++;
        }
    }

    p.setProductPrices(prices);
    productDao.merge(p);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM