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

标签 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);
}

日志:

WARNING [http-nio-8080-exec-2] org.springframework.remoting.support.RemoteInvocationTraceInterceptor.invoke Processing of HttpInvokerServiceExporter remote call resulted in fatal exception tn.waycon.alquasar2.adm.service.api.IAdminService.createRole   org.springframework.transaction.TransactionSystemException: Could not commit transaction JPA; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd) org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.BatchUpdateException: Violation of PRIMARY KEY "PK__Q2GRANT__9DB7D2FA15DA3E5D". Can not insert duplicate key in object 'dbo.Q2GRANT ". duplicate key value (13969). Error Code: 2627

最佳答案

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

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

选项有

  1. 在将现有实体添加到新实体之前读取它们 并使用托管实例。因为持续存在于托管实体上 是无操作,这将解决您的问题。
  2. 使用合并来代替。合并 允许提供者查看实体实例来决定是否 是新的或更新,并且这会按指定级联到图表。 然后合并将获取您的分离实体并处理它 适本地更新它。

关于java - 插入具有单向多对多关系的新实体生成级联持久而不是级联合并,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39775827/

相关文章:

java - 关于 ContainerBackgroundProcessor 的错误

hibernate - JPA SUM 返回长值

postgresql - JPA2 (EclipseLink) 和 PostgreSQL 的引用问题

mysql - 无法在 eclipse 中创建 jpa 表

java - 对链表中的值进行排序

java - 使用 ElasticSearch Java API 模糊查询日期

java - JSP 声明 scriptlet 访问 bean

java - Java 中的 Excel 生成问题

java - Hibernate:添加一个对象(如果尚不存在)

java - 是否可以在 jpa 的辅助表上有鉴别器列