JPA 非法状态异常 - CascadeType 问题

Posted

技术标签:

【中文标题】JPA 非法状态异常 - CascadeType 问题【英文标题】:JPA illegalStateException - CascadeType issues 【发布时间】:2011-08-09 15:58:33 【问题描述】:

我希望有人可以为我阐明这一点。我真的不明白这个错误出了什么问题。我有一个实体,用于在数据库中创建多个条目。当事务结束并且同步完成时,我得到了一个非法状态异常。这一切都在从提供所有数据的 Web 服务中填充数据库的过程中。现在我已经以一种不会导致任何外键约束错误但与实体的关系阻止我的方式解析数据。

Caused by: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: entities.cmic.ajrs.com.Categories[pkId=null].

我尝试保留的实体称为 ProductBase。 ProductBase 有一个名为 pkBrand 的外键,指向 Brand_Data 表和对应的实体 BrandData。

我可以将这些关系的 CascadeType 设置为 ALL,但此时我真的不想创建该实体。

这里是实体(减去一些 getter 和 setter)

@Entity
@Table(name = "product_base")
@NamedQueries(
    @NamedQuery(name = "ProductBase.findAll", query = "SELECT p FROM ProductBase p"),
    @NamedQuery(name = "ProductBase.findByPkId", query = "SELECT p FROM ProductBase p WHERE p.pkId = :pkId"),
    @NamedQuery(name = "ProductBase.findByColorsAvail", query = "SELECT p FROM ProductBase p WHERE p.colorsAvail = :colorsAvail"),
    @NamedQuery(name = "ProductBase.findBySeriesName", query = "SELECT p FROM ProductBase p WHERE p.seriesName = :seriesName"),
    @NamedQuery(name = "ProductBase.findByStatusCodes", query = "SELECT p FROM ProductBase p WHERE p.statusCodes = :statusCodes"),
    @NamedQuery(name = "ProductBase.findByTs", query = "SELECT p FROM ProductBase p WHERE p.ts = :ts"))
public class ProductBase implements Serializable 
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "pk_id")
    private Integer pkId;
    @Column(name = "colors_avail")
    private String colorsAvail;
    @Column(name = "series_name")
    private String seriesName;
    @Column(name = "status_codes")
    private String statusCodes;
    @Basic(optional = false)
    @Column(name = "ts")
    @Temporal(TemporalType.TIMESTAMP)
    private Date ts;
    @OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
    private Collection<ProductSorts> productSortsCollection;
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "productBase", fetch = FetchType.LAZY)
    private MapTarget mapTarget;
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "productBase", fetch = FetchType.LAZY)
    private KeyFeatures keyFeatures;
    @JoinColumn(name = "pk_category", referencedColumnName = "pk_id")
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    private Categories categories;
    @JoinColumn(name = "pk_brand", referencedColumnName = "pk_id")
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    private BrandData brandData;
    @OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
    private Collection<PromotionsByModel> promotionsByModelCollection;
    @OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
    private Collection<ProductEnhancedFeatures> productEnhancementFeaturesCollection;
    @OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
    private Collection<SkuBasic> skuBasicCollection;
    @OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
    private Collection<ProductMeasurements> productMeasurementsCollection;

    public ProductBase() 
    


@Entity
@Table(name = "brand_data")
@NamedQueries(
    @NamedQuery(name = "BrandData.findAll", query = "SELECT b FROM BrandData b"),
    @NamedQuery(name = "BrandData.findByPkId", query = "SELECT b FROM BrandData b WHERE b.pkId = :pkId"),
    @NamedQuery(name = "BrandData.findByCommonBrandId", query = "SELECT b FROM BrandData b WHERE b.commonBrandId = :commonBrandId"),
    @NamedQuery(name = "BrandData.findByCommonBrandName", query = "SELECT b FROM BrandData b WHERE b.commonBrandName = :commonBrandName"),
    @NamedQuery(name = "BrandData.findByTs", query = "SELECT b FROM BrandData b WHERE b.ts = :ts"))
public class BrandData implements Serializable 
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "pk_id")
    private Integer pkId;
    @Column(name = "common_brand_id")
    private String commonBrandId;
    @Column(name = "common_brand_name")
    private String commonBrandName;
    @Basic(optional = false)
    @Column(name = "ts")
    @Temporal(TemporalType.TIMESTAMP)
    private Date ts;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "brandData", fetch = FetchType.LAZY)
    private Collection<ProductBase> productBaseCollection;

    public BrandData() 
    

【问题讨论】:

错误地使用复数类名... 【参考方案1】:

异常清楚地表明ProductBase 引用了未保存的Categories 实例。

如果这是故意的,并且您确实想要保存 Categories 的新实例,您可以为该关系配置级联或在保存 ProductBase 之前手动保存该实例。

否则,如果ProductBase 应该引用Categories 的现有持久实例,您需要从数据库中加载该实例,而不是创建新实例。

【讨论】:

谢谢。这就是我认为的问题所在。我尝试先提交类别保存,但没有运气。我会回去看看那个。

以上是关于JPA 非法状态异常 - CascadeType 问题的主要内容,如果未能解决你的问题,请参考以下文章

JPA CascadeType.ALL 不删除孤儿

非法监控状态异常java

onActivityResult 中的非法状态异常

jython 中的 SSL 非法状态异常

mMap.addPolyline 抛出非法状态异常

使用片段中的处理程序时出现非法状态异常