无法使用Hibernate将子对象持久保存在多对多关系中

时间:2016-08-01 19:55:39

标签: java hibernate many-to-many

我在基于Spring 4.3.1的Web应用程序中使用了hibernate 4.3.11。我有三个实体,即CostSheetEntity,RawMaterialEntity和LaborEntity。

CostSheetEntity由多个RawMaterialEntity和LaborEntity组成。并且一个RawMaterialEntity或LaborEntity可以属于多个CostSheetEntity。

为了处理这些关系,我创建了由两个名为CostSheetRawMaterialMapEntity和CostSheetLaborMapEntity的映射实体表示的映射表。这些映射表/实体还带有额外的字段,以便在成本单中保存额外的数据,如特定原材料和人工的费率和消耗。

问题陈述:我必须保存CostSheetEntity。当我尝试这样做时,只保存CostSheetEntity。相应的映射实体CostSheetRawMaterialMapEntity和CostSheetLaborMapEntity不会保存到数据库中(MySQL 5.7)。

我在做什么。以下是我的实体类代码。

CostSheetEntity

@Entity
@Table(name = "jak_md_cost_sheet", catalog = "jakerp", uniqueConstraints = @UniqueConstraint(columnNames = "COST_SHEET_NAME"))
public class CostSheetEntity implements java.io.Serializable {

    private static final long serialVersionUID = -3249250828933375991L;
    private Integer id;
    private BuyerEntity buyerEntity;
    private EmployeeEntity employeeEntity;
    private ProductCategoryEntity productCategoryEntity;
    private String costSheetName;
    private String description;

    private Set<CostSheetLaborMapEntity> costSheetLaborMapEntities = new HashSet<CostSheetLaborMapEntity>(0);
    private Set<CostSheetRawMaterialMapEntity> costSheetRawMaterialMapEntities = new HashSet<CostSheetRawMaterialMapEntity>(0);
    private Set<StyleEntity> styleEntities = new HashSet<StyleEntity>(0);


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "BUYER_ID")
    public BuyerEntity getBuyerEntity() {
        return this.buyerEntity;
    }

    public void setBuyerEntity(BuyerEntity buyerEntity) {
        this.buyerEntity = buyerEntity;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "MERCHANT_ID")
    public EmployeeEntity getEmployeeEntity() {
        return this.employeeEntity;
    }

    public void setEmployeeEntity(EmployeeEntity employeeEntity) {
        this.employeeEntity = employeeEntity;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PRODUCT_CATEGORY", nullable = false)
    public ProductCategoryEntity getProductCategoryEntity() {
        return this.productCategoryEntity;
    }

    public void setProductCategoryEntity(ProductCategoryEntity productCategoryEntity) {
        this.productCategoryEntity = productCategoryEntity;
    }

    @Column(name = "COST_SHEET_NAME", unique = true, nullable = false, length = 100)
    public String getCostSheetName() {
        return this.costSheetName;
    }

    public void setCostSheetName(String costSheetName) {
        this.costSheetName = costSheetName;
    }

    @Column(name = "DESCRIPTION", length = 500)
    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "costSheetEntity")
    public Set<CostSheetLaborMapEntity> getCostSheetLaborMapEntities() {
        return this.costSheetLaborMapEntities;
    }

    public void setCostSheetLaborMapEntities(Set<CostSheetLaborMapEntity> costSheetLaborMapEntities) {
        this.costSheetLaborMapEntities = costSheetLaborMapEntities;
    }

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "costSheetEntity")
    public Set<CostSheetRawMaterialMapEntity> getCostSheetRawMaterialMapEntities() {
        return this.costSheetRawMaterialMapEntities;
    }

    public void setCostSheetRawMaterialMapEntities(Set<CostSheetRawMaterialMapEntity> costSheetRawMaterialMapEntities) {
        this.costSheetRawMaterialMapEntities = costSheetRawMaterialMapEntities;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "costSheetEntity")
    public Set<StyleEntity> getStyleEntities() {
        return this.styleEntities;
    }

    public void setStyleEntities(Set<StyleEntity> styleEntities) {
        this.styleEntities = styleEntities;
    }

    public static long getSerialversionuid() {
        return serialVersionUID;
    }
}

RawMaterialEntity

@Entity
@Table(name = "jak_md_raw_material", catalog = "jakerp", uniqueConstraints = @UniqueConstraint(columnNames = "MATERIAL_NAME"))
public class RawMaterialEntity implements java.io.Serializable {

    private static final long serialVersionUID = 3037539645227982760L;
    private Integer id;
    private RawMaterialCategoryEntity rawMaterialCategoryEntity;
    private UnitOfMeasureEntity unitOfMeasureEntityByUnitGeneral;
    private UnitOfMeasureEntity unitOfMeasureEntityByUnitThickness;
    private String materialName;
    private String description;
    private Set<CostSheetRawMaterialMapEntity> costSheetRawMaterialMapEntities = new HashSet<CostSheetRawMaterialMapEntity>(
            0);

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "RAW_MATERIAL_CATEGORY_ID", nullable = false)
    public RawMaterialCategoryEntity getRawMaterialCategoryEntity() {
        return this.rawMaterialCategoryEntity;
    }

    public void setRawMaterialCategoryEntity(RawMaterialCategoryEntity rawMaterialCategoryEntity) {
        this.rawMaterialCategoryEntity = rawMaterialCategoryEntity;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "UNIT_GENERAL")
    public UnitOfMeasureEntity getUnitOfMeasureEntityByUnitGeneral() {
        return this.unitOfMeasureEntityByUnitGeneral;
    }

    public void setUnitOfMeasureEntityByUnitGeneral(UnitOfMeasureEntity unitOfMeasureEntityByUnitGeneral) {
        this.unitOfMeasureEntityByUnitGeneral = unitOfMeasureEntityByUnitGeneral;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "UNIT_THICKNESS")
    public UnitOfMeasureEntity getUnitOfMeasureEntityByUnitThickness() {
        return this.unitOfMeasureEntityByUnitThickness;
    }

    public void setUnitOfMeasureEntityByUnitThickness(UnitOfMeasureEntity unitOfMeasureEntityByUnitThickness) {
        this.unitOfMeasureEntityByUnitThickness = unitOfMeasureEntityByUnitThickness;
    }

    @Column(name = "MATERIAL_NAME", unique = true, nullable = false, length = 100)
    public String getMaterialName() {
        return this.materialName;
    }

    public void setMaterialName(String materialName) {
        this.materialName = materialName;
    }

    @Column(name = "DESCRIPTION", length = 500)
    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @OneToMany(mappedBy = "rawMaterialEntity")
    public Set<CostSheetRawMaterialMapEntity> getCostSheetRawMaterialMapEntities() {
        return this.costSheetRawMaterialMapEntities;
    }

    public void setCostSheetRawMaterialMapEntities(Set<CostSheetRawMaterialMapEntity> costSheetRawMaterialMapEntities) {
        this.costSheetRawMaterialMapEntities = costSheetRawMaterialMapEntities;
    }

}

CostSheetRawMaterialMapEntity

@Entity
@Table(name = "jak_md_cost_sheet-raw_material", catalog = "jakerp")
public class CostSheetRawMaterialMapEntity implements java.io.Serializable {

    private Integer id;
    private CostSheetEntity costSheetEntity;
    private RawMaterialEntity rawMaterialEntity;
    private BigDecimal consumption;
    private BigDecimal rate;
    private BigDecimal lineTotal;

    public CostSheetRawMaterialMapEntity() {
    }

    public CostSheetRawMaterialMapEntity(CostSheetEntity costSheetEntity, RawMaterialEntity rawMaterialEntity,
            BigDecimal consumption, BigDecimal rate, BigDecimal lineTotal) {
        this.costSheetEntity = costSheetEntity;
        this.rawMaterialEntity = rawMaterialEntity;
        this.consumption = consumption;
        this.rate = rate;
        this.lineTotal = lineTotal;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "COST_SHEET_ID", nullable = false)
    public CostSheetEntity getCostSheetEntity() {
        return this.costSheetEntity;
    }

    public void setCostSheetEntity(CostSheetEntity costSheetEntity) {
        this.costSheetEntity = costSheetEntity;
    }

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "RAW_MATERIAL_ID", nullable = false)
    public RawMaterialEntity getRawMaterialEntity() {
        return this.rawMaterialEntity;
    }

    public void setRawMaterialEntity(RawMaterialEntity rawMaterialEntity) {
        this.rawMaterialEntity = rawMaterialEntity;
    }

    @Column(name = "CONSUMPTION", nullable = false, precision = 10)
    public BigDecimal getConsumption() {
        return this.consumption;
    }

    public void setConsumption(BigDecimal consumption) {
        this.consumption = consumption;
    }

    @Column(name = "RATE", nullable = false, precision = 10)
    public BigDecimal getRate() {
        return this.rate;
    }

    public void setRate(BigDecimal rate) {
        this.rate = rate;
    }

    @Column(name = "LINE_TOTAL", nullable = false, precision = 10)
    public BigDecimal getLineTotal() {
        return this.lineTotal;
    }

    public void setLineTotal(BigDecimal lineTotal) {
        this.lineTotal = lineTotal;
    }

}

与原材料实体类似,也存在劳动实体。当要保存CostSheetEntity时,这两个子实体也应该插入和/或更新到数据库中。

我与数据库交互的方式是使用DAO,而DAO又使用以下DBUtil类来执行实际的数据库操作:

/**
 * The Class HibernateUtil. This class is a wrapper on Hibernate methods to perform CRUD operations with Entities
 */
@Repository
public class HibernateUtil {

    /** The Constant logger. */
    private static final Logger logger = Logger.getLogger(HibernateUtil.class);

    /** The session factory. */
    @Autowired
    private SessionFactory sessionFactory;

    /**
     * Instantiates a new hibernate util.
     */
    public HibernateUtil() {
        logger.info("Inside constructor of class" + logger.getName());
    }

    /**
     * Persist the given transient instance, first assigning a generated identifier. 
     * (Or using the current value of the identifier property if the assigned generator is used.) 
     * This operation cascades to associated instances if the association is mapped with cascade="save-update".
     *
     * @param <T> the generic type
     * @param entity the entity
     * @return the serializable
     */
    // Record Create Methods
    public <T> Serializable create(final T entity) throws HibernateException{
        return sessionFactory.getCurrentSession().save(entity);
    }

    /**
     * Read all records for the passed Entity class. Create a Query instance for the passed Class instance and returns the query results as a List. 
     * If the query contains multiple results per row, the results are returned in an instance of Object[].
     *
     * @param <T> the generic type
     * @param entityClass the entity class
     * @return the list
     */
    // Record retrieval Methods
    @SuppressWarnings("unchecked")
    public <T> List<T> readAll(Class<T> entityClass) throws HibernateException{
        return sessionFactory.getCurrentSession().createQuery(" FROM " + entityClass.getName()).list();
    }

    /**
     * Read records through hql. Create a Query instance for the given HQL query string and eturn the query results as a List. If the query contains multiple results per row, 
     * the results are returned in an instance of Object[].
     *
     * @param <T> the generic type
     * @param hqlQuery the hql query
     * @return the list
     */
    @SuppressWarnings("unchecked")
    public <T> List<T> readAllThroughHQL(String hqlQuery) throws HibernateException{
        return sessionFactory.getCurrentSession().createQuery(hqlQuery).list();
    }

    /**
     * Read records through sql. Create a SQLQuery instance for the given SQL query string. Return the query results as a List. 
     * If the query contains multiple results per row, the results are returned in an instance of Object[].
     *
     * @param <T> the generic type
     * @param sqlQuery the sql query
     * @return the list
     */
    @SuppressWarnings("rawtypes")
    public <T> List readAllThroughSQL(String sqlQuery) throws HibernateException {
        return sessionFactory.getCurrentSession().createSQLQuery(sqlQuery).list();
    }

    /**
     * Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. 
     * (If the instance is already associated with the session, return that instance. This method never returns an uninitialized instance.)
     *
     * @param <T> the generic type
     * @param id the id
     * @param entityClass the entity class
     * @return the t
     */
    @SuppressWarnings("unchecked")
    public <T> T readById(Serializable id, Class<T> entityClass) throws HibernateException {
        return (T) sessionFactory.getCurrentSession().get(entityClass, id);
    }

    /**
     * Update the persistent instance with the identifier of the given detached instance. If there is a persistent instance with the same identifier, an exception is thrown. 
     * This operation cascades to associated instances if the association is mapped with cascade="save-update"
     *
     * @param <T> the generic type
     * @param entity the entity
     * @return the t
     */
    // Record update Methods
    public <T> T update(final T entity) throws HibernateException {
        sessionFactory.getCurrentSession().update(entity);
        return entity;
    }

    /**
     * Either save(Object) or update(Object) the given instance, depending upon resolution of the unsaved-value checks (see the manual for discussion of unsaved-value checking). 
     * This operation cascades to associated instances if the association is mapped with cascade="save-update".
     *
     * @param entityObject the entity object
     */
    public void createOrUpdate(Object entityObject) throws HibernateException {
        sessionFactory.getCurrentSession().saveOrUpdate(entityObject);
    }

    /**
     * Remove a persistent instance from the datastore. The argument may be an instance associated with the receiving Session or a transient instance with an identifier associated 
     * with existing persistent state. This operation cascades to associated instances if the association is mapped with cascade="delete"
     *
     * @param <T> the generic type
     * @param entity the entity
     */
    // Record delete Methods
    public <T> void delete(final T entity) throws HibernateException {
        sessionFactory.getCurrentSession().delete(entity);
    }

    /**
     * First retrieve the entity from database by using the id passed and then Remove it from the database using same retrieved entity object.
     *
     * @param <T> the generic type
     * @param id the id
     * @param entityClass the entity class
     */
    public <T> void delete(Serializable id, Class<T> entityClass) throws HibernateException{
        T entity = readById(id, entityClass);
        delete(entity);
    }

}

0 个答案:

没有答案