插入具有单向多对多关系的新实体生成级联持久而不是级联合并

时间:2016-09-29 16:44:51

标签: java hibernate eclipselink

我有两个实体Role和Grant,其中包含以下映射:

public class Role extends BaseBean {
    private static final long            serialVersionUID   = 1L;
    private String                     name;
    private Set<Grant> grants = new HashSet<Grant>();
// get set
}

public class Grant implements Serializable {
    private static final long   serialVersionUID    = 1L;
    private String            id;
    private String            data;
}

映射orm:

 <entity name="q2role" class="tn.waycon.alquasar2.adm.model.Role">
        <attributes>
            <basic name="name">
                <column length="800" nullable="false" unique="true"/>
            </basic>
            <many-to-many name="grants" fetch="EAGER">
                <join-table name="role_grant">
                    <join-column name="role_id"/>
                    <inverse-join-column name="grant_id"/>
                </join-table>
                <cascade>
                    <cascade-all/>
                </cascade>
            </many-to-many>
        </attributes>
    </entity>

<entity name="q2grant" class="tn.waycon.alquasar2.adm.model.Grant">
        <attributes>
            <id name="id">
                <column name="id_g"/>
                <generated-value stategy="IDENTITY" generator="SEQ_GEN"/>
            </id>
            <basic name="data"></basic>
        </attributes>
</entity>

现在,当我尝试插入包含现有授权的新角色时,事务将失败,因为eclipselink正在尝试插入已存在的授权。为什么eclipselink正在做这种奇怪的行为?我正在设置cascade-all和eclipselink必须足够智能,以便在cascade-persist和cascade-merge之间分开。

Main {
Role role = new Role();
List<Grant> grants = grantRepository.getGrantsBydata(List<String> datas);
role.setGrants(grants);
roleRepository.save(role);
}

日志:

  

警告[http-nio-8080-exec-2]   org.springframework.remoting.support.RemoteInvocationTraceInterceptor.invoke   处理HttpInvokerServiceExporter远程调用导致致命   例外tn.waycon.alquasar2.adm.service.api.IAdminService.createRole   org.springframework.transaction.TransactionSystemException:可以   不承诺交易JPA;嵌套异常是   javax.persistence.RollbackException:异常[EclipseLink-4002]   (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd)   org.eclipse.persistence.exceptions.DatabaseException内部   例外:java.sql.BatchUpdateException:违反PRIMARY KEY   “PK__Q2GRANT__9DB7D2FA15DA3E5D”。无法插入重复键   object'dbo.Q2GRANT“。重复键值(13969)。错误代码:2627

2 个答案:

答案 0 :(得分:1)

调用Persist会导致JPA插入根实体,但它也会在标记为级联持久类型的关系中级联持久调用。这间接意味着您在分离的实体上调用persist,JPA规范要求提供程序立即或在事务与数据库同步时(insert语句)抛出异常。

Persist和cascade persist选项仅用于在您要插入新对象图时使用,因此您可能需要重新评估您在cascade persist选项中的位置 - 它会产生后果。

选项

  1. 在将现有实体添加到新实体之前读取它们 并使用托管实例。因为坚持管理实体 这是一个无操作,这将解决您的问题。
  2. 请改用合并。合并     允许提供者查看实体实例以确定它是否存在     是新的或更新,并按指定级联到图表。     然后合并将获取您的分离实体并处理它     适当地通过更新它。

答案 1 :(得分:0)

您应该删除,因为Grants与角色分开管理。 使用意味着在插入角色时,还会插入其所有授权,并且在删除授权时,也会删除授权。 在您的情况下,我可以看到创建角色时Grants已经存在,因此您不希望在删除该角色时删除它们!