1

我想创建和删除ProductPrice之一,更新工作正常但其他人给出异常

产品类别

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>();
}

产品价格等级

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);
}

如果价格是在同一个会话上创建的,删除操作是成功的,但是,如果它是在当前会话之前创建的,它会抛出这个错误

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)

我没有完全得到 MapKeyJoinColumn,也找不到关于这种情况的文档。我认为地图列表缓存会导致此错误。任何准备充分的文档建议也都会获得批准。

4

2 回答 2

0

我假设在调用之前removeProductPrice()你打开一个会话并开始一个事务。

在该removeProductPrice()方法中,通过执行 get() 将 productPrice 对象加载到持久性上下文。像,

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

// Then your logic to delete.

我怀疑传递ProductPrice给该removeProductPrice()方法的对象不存在于会话的持久性上下文中。

您能否发布完整的堆栈跟踪,显示导致异常的确切行。

于 2013-06-19T12:38:30.233 回答
0

我找到的最后一个解决方案是;

真正的问题是同一个对象在两个不同的列表缓存中。因此,当您更改其中之一时,根据您选择的 FetchType 方法会导致错误。

如果您将 FetchTypes 定义为FetchType.EagerFetchType.SUBSELECTCacheConcurrencyStrategy.READ_WRITE,您可以通过更改缓存两侧的对象轻松地进行 crud!即你想删除其中一个价格,你也应该从productPriceMap&中删除它productPrices。然后merge product;就完成了!

    @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 服务

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);
}
于 2013-07-10T11:39:52.470 回答