为什么持久化实体两次避免了对具有连接列的实体进行级联的错误

时间:2018-03-15 07:07:51

标签: java jpa java-ee

如果我不分两步执行实体角色设置(两个持续存在),为什么此单元测试失败。 错误是:

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: io.osram.olt.extension.jpa.Role@16daa399.

    private Role addRoleWithId(String roleId){
        Role myRole = new Role();
        myRole.setRoleId(roleId);
        myRole.setRealmId("my");
        myRole.setDescription("role-description-0");
        myRole.setExternalCreator(true);
        myRole.setName("role-name-0");
        em.persist(myRole); //<--- Without this persisting the role fails with the error above.

        //Setup joins:
        myRole.setAContext(getApplications().get(0));
        myRole.setAnotherContext(getTenants().get(0));
        em.persist(myRole);
        return myRole;
    }

...

角色实体:

        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "ANOTHER_CONTEXT_ID")
        private AnotherContext anotherContext;

        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "ACONTEXT_ID")
        private AContext aContext;

    ...
        public Role setAContext(AContext aContext) {
            this.aContext = aContext;
            if(aContext != null) {
                aContext.addRole(this);
            }
            return this;
        }

        public Role setAnotherContext(AnotherContext anotherContext) {
            this.anotherContext = anotherContext;
            if(anotherContext != null){
                anotherContext.addRole(this);
            }
            return this;
        }

    ...

AContext和AnotherContext都包含与角色类似的关系:

@OneToMany
@JoinTable(
        name="OLT_ROLES_ACONTEXT",
        joinColumns = @JoinColumn( name="ACONTEXT_ID"),
        inverseJoinColumns = @JoinColumn( name="ROLE_ID")
)
private Set<Role> roles = new HashSet<Role>();

似乎通过两步创建对象,我可以避免使用级联。

2 个答案:

答案 0 :(得分:0)

setAContextsetAnotherContext方法中,您正在尝试设置尚未保留的Role对象。 很明显,在设置上下文之前,如果没有指定em.persist(myRole);,它将无法使用CaseCadeType.PERSIST

答案 1 :(得分:0)

级联的默认设置是级联NONE,这会导致默认情况下持久化实体中的关系不会保留。

必然结果是,如果在没有管理关系的情况下尝试将没有cascade.PERSIST的实体持久化到它的关系,则会得到上述异常。

推论的一个例外是,如果您持久存在的实体是关系的所有者,并且关系中的属性已经存在于数据库中,则yo将能够保留它。

我在映射中注意到的一件小事:它是一个双向单向,一个带有连接列,另一个带有连接表,所以这是有意的吗?