Hibernate双向多对多删除元素抛出异常

时间:2014-10-22 00:52:58

标签: hibernate-mapping

我在两个类Project和ProductCatalogItem之间有一个双向的多对多映射。 Project hbm文件中定义的映射如下 -

<set name="catalogItems" table="PAS_PRODUCT_CATALOG_PROJECT"
     inverse="false" lazy="true" cascade="all-delete-orphan">
    <key column="PROJECT_ID_" />
    <many-to-many column="PRODUCT_CATALOG_ITEM_ID_" class="com.palamida.appsec.model.ProductCatalogItem" />
</set>

ProductCatalogItem中的映射定义如下 -

<set name="itemInProjects" table="PAS_PRODUCT_CATALOG_PROJECT"
     inverse="true" lazy="true">
    <key column="PRODUCT_CATALOG_ITEM_ID_" />
    <many-to-many column="PROJECT_ID_" class="com.palamida.appsec.model.Project" />
</set>

定义了三个表格 - PROJECT,PRODUCT_CATALOG_ITEM和PAS_PRODUCT_CATALOG_PROJECT(联接表)

Project类具有catalogItems

private Set<ProductCatalogItem> catalogItems = new HashSet<ProductCatalogItem>();

ProductCatalogItem具有itemsInProject

private Set<Project> itemInProjects = new HashSet<Project>();

每个属性都有适当的getter和setter。 从ProductCatalogItem添加/删除项目的逻辑如下 -

public void updateProductCatalogItemsToProject(Project project,
                                        Map<EntityOperationEnum,Set<ProductCatalogItem>> modifiedCatalogItems) {
    if (project != null && modifiedCatalogItems != null && !modifiedCatalogItems.isEmpty()) {
        Set<ProductCatalogItem> newCatalogItems = modifiedCatalogItems.get(EntityOperationEnum.ADD);
        Set<ProductCatalogItem> deleteCatalogItems = modifiedCatalogItems.get(EntityOperationEnum.REMOVE);

        if (newCatalogItems != null && !newCatalogItems.isEmpty()) {
            project.getCatalogItems().addAll(newCatalogItems);    
        }
        if (deleteCatalogItems != null && !deleteCatalogItems .isEmpty()) {
            project.getCatalogItems().removeAll(deleteCatalogItems );    
        }
    }
}

当只有要添加的元素时,数据将插入到链接表中。但是当要删除项目时,我会遇到以下异常 -

org.springframework.dao.InvalidDataAccessResourceUsageException: could not initialize a collection: [com.palamida.appsec.model.ProductCatalogItem.childProductCatalogItems#17]; SQL [select   childprodu0_.PROJECT_ID_ as PROJECT9_89_1_, childprodu0_.ID_ as ID1_1_, childprodu0_.ID_ as ID1_89_0_, childprodu0_.VERSION_ as VERSION2_89_0_, childprodu0_.ITEM_NUMBER_ as ITEM3_89_0_,  childprodu0_.ITEM_NAME_ as ITEM4_89_0_, childprodu0_.ITEM_DESCRIPTION_ as ITEM5_89_0_, childprodu0_.PLATFORM_NAME_ as PLATFORM6_89_0_, childprodu0_.RELEASE_NAME_ as RELEASE7_89_0_, childprodu0_.PARENT_ID_ as PARENT8_89_0_ from PAS_PRODUCT_CATALOG_ITEM childprodu0_ where childprodu0_.PROJECT_ID_=? order by childprodu0_.ITEM_NAME_ asc]; nested exception is org.hibernate.exception.SQLGrammarException: could not initialize a collection:  [com.palamida.appsec.model.ProductCatalogItem.childProductCatalogItems#17]
at    org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:635)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column   'childprodu0_.PROJECT_ID_' in 'field list'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57

SELECT是否应该根据PROJECT_ID_在PAS_PRODUCT_CATALOG_PROJECT表上加入?我没有看到这种情况发生。地图中是否有任何遗漏? 你能帮帮我吗?

1 个答案:

答案 0 :(得分:0)

我发现了这个问题。我的映射是cascade =&#34; all-delete-orphan&#34;。根据hibernate docs

It does not usually make sense to enable cascade on a many-to-one or many-to-many association. 
In fact the @ManyToOne and @ManyToMany don't even offer a orphanRemoval attribute. 
Cascading is often useful for one-to-one and one-to-many associations.

因此,当我尝试从关联中删除时,hibernate尝试使用连接列&#34; PROJECT_ID _&#34;将其从CATALOG_ITEM表中删除。因此错误。 一旦我将其修改为&#34; all&#34;,事情就开始起作用了。