Java Hibernate JPA删除OneToMany关系和MapKeyJoinColumn关系对象

Java Hibernate JPA删除OneToMany关系和MapKeyJoinColumn关系对象,java,hibernate,caching,one-to-many,Java,Hibernate,Caching,One To Many,我想创建并删除ProductPrice中的一个, 更新工作正常,但其他人给出了例外 产品类别 public class Product extends GenericEntity { @OneToMany(fetch=FetchType.EAGER, mappedBy = "product", targetEntity = ProductPrice.class, cascade = {CascadeType.ALL}, orphanRemoval=true) @Fetch(Fet

我想创建并删除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);
}

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

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

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

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


你能发布完整的堆栈跟踪吗?它显示了导致异常的确切行。

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

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

如果将FetchType定义为FetchType.EagerFetchType.SUBSELECTcacheconcurrencysttrategy.READ\u WRITE,则可以通过更改缓存两侧的对象轻松进行crud!i、 e.如果您想删除price中的一个,也应该将其从
productPriceMap
productPrices
中删除。然后
合并产品它已经完成了

    @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>();
@OneToMany(fetch=FetchType.EAGER,mappedBy=“product”,targetEntity=ProductPrice.class,cascade={CascadeType.ALL},orphanRemoving=true)
@Fetch(FetchMode.SUBSELECT)
@缓存(用法=cacheconcurrentystrategy.READ\u WRITE,region=“ncStandardElements”)
private List productPrices=new ArrayList();
@OneToMany(fetch=FetchType.EAGER,mappedBy=“product”,targetEntity=ProductPrice.class)
@Fetch(FetchMode.SUBSELECT)
@MapKeyJoinColumn(name=“CURRENCY\u ID”)
@缓存(用法=cacheconcurrentystrategy.READ\u WRITE,region=“ncStandardElements”)
私有映射productPriceMap=新HashMap();
在役积垢

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);
}
public void removeProductPrice(ProductPrice价格){
产品p=price.getProduct();
Map productPriceMap=p.getProductPriceMap();
productPriceMap.remove(价格);
标价=p.getProductPrices();
价格。删除(价格);
p、 设定产品价格(价格);
p、 移除ProductPriceMap(价格);
合并(p);
}
public void saveProductPrice(ProductPrice,布尔值isNew){
产品p=price.getProduct();
标价=p.getProductPrices();
如果(是新的){
价格。添加(价格);
}
否则{
int i=0;
对于(产品价格tp:价格){
if(tp.getId()==price.getId()){
价格。设定(i,价格);
打破
}
i++;
}
}
p、 设定产品价格(价格);
合并(p);
}

productDao.merge(p)行原因错误。我不断地更改代码并尝试其他属性。实际上,我已经解决了这个问题,为这两个关系定义了
FetchType.Eager、FetchType.SUBSELECT
cacheconcurrencysttrategy.READ\u WRITE
,但是,这并不是我们项目的最佳配置。现在,我想配置关系wihtout
FetchType.Eager
@kirlisakal您尝试过我提到的解决方案了吗?实际上,现在情况不同了。当您试图在
产品
类上进行crud时,两个关系会导致错误。毕竟,我必须从
PriceDao
中添加或删除
Price
。在这种情况下,问题在于缓存。当我得到
ProductPrice
list时,我通过刷新缓存解决了这个问题。
    @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>();
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);
}