@OneToOne需要CascadeType.MERGE吗?

时间:2013-04-02 02:20:42

标签: jpa merge cascade one-to-one

具有以下装饰和条件,

/**
 * passsalt.
 */
@JoinColumn(name = "PASSSALT_ID", nullable = false)
@OneToOne(cascade = {CascadeType.PERSIST,
                     CascadeType.MERGE, // is this actually required?
                     CascadeType.REMOVE},
          optional = false, orphanRemoval = true)
@NotNull
@XmlTransient
private Morton passsalt;
  • passsalt必须与此实体一起持续使用。 (CascadeType.PERSIST
  • passsalt可以替换为新的detached实例。 (CascadeType.MERGE?)
  • 删除此实体后,必须删除
  • passsalt。 (CascadeType.REMOVE
  • Morton没有要更新的字段

问题:CascadeType.MERGE是强制性的吗?

我使用和不使用CascadeType.MERGE进行了测试,没有它就可以正常工作。

Q2:问题标题中的“Is”是否正确?它应该是“有”吗?

以下是替换passsalt的方法。

public boolean nassword(final Shadow reference, final byte[] password,
                        final byte[] nassword) {

    passsalt = new Morton();
    passcode = passsalt.salty(nassword);

    return true;
}

我用以下方法测试过。

@Test(enabled = true, invocationCount = 1)
public void testNassword0() {
    final EntityManager manager = LocalPU.createEntityManager();
    try {
        final EntityTransaction transaction = manager.getTransaction();
        transaction.begin();
        try {
            final String username = newUsername(manager);
            final byte[] password = newPassword();
            Shadow shadow = persistInstance(manager, username, password);
            Assert.assertTrue(shadow.puthenticate(shadow, password));
            System.out.println("=========================================");
            LOGGER.log(Level.INFO, "mortons: {0}",
                       MORTONS(manager, 0, 1024));
            final byte[] nassword = newPassword();
            shadow.nassword(shadow, password, nassword);
            shadow = manager.merge(shadow);
            manager.flush();
            System.out.println("=========================================");
            LOGGER.log(Level.INFO, "mortons: {0}",
                       MORTONS(manager, 0, 1024));
            Assert.assertFalse(shadow.puthenticate(shadow, password));
            Assert.assertTrue(shadow.puthenticate(shadow, nassword));
            transaction.commit();
        } catch (Exception e) {
            transaction.rollback();
            e.printStackTrace(System.err);
            Assert.fail(e.getMessage());
        }
    } finally {
        manager.close();
    }
}

这是输出。

4월 02, 2013 11:55:03 오전 org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 4.3.0.Final
[EL Info]: 2013-04-02 11:55:03.897--ServerSession(571229670)--EclipseLink, version: Eclipse Persistence Services - 2.3.2.v20111125-r10461
[EL Info]: 2013-04-02 11:55:04.744--ServerSession(571229670)--file:/E:/svnwc/jinahya.googlecode.com/trunk/com.googlecode.jinahya/jinahya-ee/target/test-classes/_localPU login successful
4월 02, 2013 11:55:06 오전 com.googlecode.jinahya.persistence.Morton _PrePersist
INFO: _PrePersist(): Morton@1760972179&id=1048576
4월 02, 2013 11:55:06 오전 com.googlecode.jinahya.persistence.Shadow puthenticate
INFO: puthenticate(Shadow@1311874806?id=1048576&username=0KIWHFirmA581Qf5AscsrVbN9YW30pAF&passcode=[B@57d01cc, [B@5200fae4)
4월 02, 2013 11:55:06 오전 com.googlecode.jinahya.persistence.Shadow puthenticate
INFO: passsalt: Morton@1760972179&id=1048576
=========================================
4월 02, 2013 11:55:08 오전 com.googlecode.jinahya.persistence.ShadowTest testNassword0
INFO: mortons: [Morton@1760972179&id=1048576]
4월 02, 2013 11:55:08 오전 com.googlecode.jinahya.persistence.Shadow nassword
INFO: nassword(Shadow@1311874806?id=1048576&username=0KIWHFirmA581Qf5AscsrVbN9YW30pAF&passcode=[B@57d01cc, [B@5200fae4, [B@1b6ac76b)
4월 02, 2013 11:55:08 오전 com.googlecode.jinahya.persistence.Shadow puthenticate
INFO: puthenticate(Shadow@1311874806?id=1048576&username=0KIWHFirmA581Qf5AscsrVbN9YW30pAF&passcode=[B@57d01cc, [B@5200fae4)
4월 02, 2013 11:55:08 오전 com.googlecode.jinahya.persistence.Shadow puthenticate
INFO: passsalt: Morton@1760972179&id=1048576
4월 02, 2013 11:55:11 오전 com.googlecode.jinahya.persistence.Morton _PrePersist
INFO: _PrePersist(): Morton@93935309&id=1048577
=========================================
4월 02, 2013 11:55:11 오전 com.googlecode.jinahya.persistence.ShadowTest testNassword0
INFO: mortons: [Morton@93935309&id=1048577]
4월 02, 2013 11:55:11 오전 com.googlecode.jinahya.persistence.Shadow puthenticate
INFO: puthenticate(Shadow@1311874806?id=1048576&username=0KIWHFirmA581Qf5AscsrVbN9YW30pAF&passcode=[B@641e8314, [B@5200fae4)
4월 02, 2013 11:55:11 오전 com.googlecode.jinahya.persistence.Shadow puthenticate
INFO: passsalt: Morton@93935309&id=1048577
4월 02, 2013 11:55:12 오전 com.googlecode.jinahya.persistence.Shadow puthenticate
INFO: puthenticate(Shadow@1311874806?id=1048576&username=0KIWHFirmA581Qf5AscsrVbN9YW30pAF&passcode=[B@641e8314, [B@1b6ac76b)
4월 02, 2013 11:55:12 오전 com.googlecode.jinahya.persistence.Shadow puthenticate
INFO: passsalt: Morton@93935309&id=1048577

总之,

After persisted ->           mortons: [Morton@1760972179&id=1048576]
After replaced and merged -> mortons: [Morton@93935309&id=1048577]

1 个答案:

答案 0 :(得分:3)

简短回答,不是必需的。

级联持久化和合并是不同的事情。当您在拥有实体上调用persist时会使用Cascade Persist,从而导致在引用的passsalt上调用persist。如果关系中存在级联持久性,则暗示在调用flush或commit时也会发现引用新对象。

另一方面,合并以相同的方式应用于合并操作。当您在实体上调用merge时,它将导致在passsalt上调用merge。如果它存在并且刚刚分离,则将获取更改。如果它是新的,它将被插入类似于if persist被调用。当没有指定级联合并并且关系引用分离的对象时,会发生什么情况,但是如果实体是新的,则看起来很灰暗。它声明返回的拥有实体引用了passsalt的托管实例,这意味着无论如何都会插入它,因为托管实例需要在刷新或提交时与数据库同步。所以它应该没有效果,但取决于你如何使用merge api以及你的JPA提供程序的行为,你可能想要保持它的设置。没有它意味着改变现有的passsalt(如果你当然不只是替换它)将不会被接收。

此外,您正在使用orphanRemoval,因此暗示并不需要级联删除。 OrphanRemoval意味着在没有所有者实体的情况下引用的passsalt不存在,因此当删除所有者或取消引用passsalt时,它将从数据库中删除而不需要级联删除设置。