java - 仅具有 CascadeType.REMOVE 的双向 @OneToOne 保存更改 : that is not wanted

标签 java jpa orm eclipselink

问题:

我有两个实体,SomeEntitySomeEntityInfo,它们处于双向一对一关系,仅具有 CascadeType.REMOVE 级联集。

如果 SomeEntity.someEntityInfo 发生更改,并且 SomeEntity 已(已存在)保存 -> 不应对 SomeEntityInfo 表/对象进行级联数据库更新。

但是相关实体也会更新

编辑/更新 换句话说:我希望 SomeEntityInfo 是“(某种程度上)不可变的”。它应该在创建 SomeEntity 时创建,但不更新/检查版本 - 乐观锁定 - 如果重新保存 SomeEntity

到目前为止我做了什么

  • SomeEntity 的 getter 中返回 SomeEntityInfo 的副本会导致

    a new object was found through a relationship that was not marked cascade PERSIST [..]

  • (拼命地)用注释

    @OneToOne(cascade = { CascadeType.REMOVE })
    @JoinColumn(name = "someentityinfo_id", updatable = false, insertable = true)
    private SomeEntityInfo someEntityInfo;
    

    与外键的ID有关,与引用对象内部的数据无关

示例 - 数据库架构(mysql db)

    CREATE TABLE someentity (
      id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
      version INT(11) NULL DEFAULT NULL,
      someentityinfo_id INT(11) UNSIGNED NULL DEFAULT NULL,
      PRIMARY KEY (id)
    )
    COLLATE='utf8_general_ci'
    ENGINE=InnoDB;

    CREATE TABLE someentityinfo (
      id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
      version INT(11) NULL DEFAULT NULL,
      status varchar(255) DEFAULT NULL,
      PRIMARY KEY (id)
    )
    COLLATE='utf8_general_ci'
    ENGINE=InnoDB;

    ALTER TABLE someentity
      ADD INDEX FK_someentityinfo_id (someentityinfo_id);

    ALTER TABLE someentity
      ADD CONSTRAINT FK_someentityinfo_id FOREIGN KEY (someentityinfo_id) REFERENCES someentityinfo (id);

实体代码

某个实体

    import javax.persistence.CascadeType;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.OneToOne;
    import javax.persistence.Table;
    import javax.persistence.Version;

    @Entity
    @Table(name = "someentity")
    public class SomeEntity {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;

        @Version
        private Integer version;

        @OneToOne(cascade = { CascadeType.REMOVE })
        @JoinColumn(name = "someentityinfo_id")
        private SomeEntityInfo someEntityInfo;
        [getter/setter]
    }

一些实体信息

    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.OneToOne;
    import javax.persistence.Table;
    import javax.persistence.Version;

    @Entity
    @Table(name = "someentityinfo")
    public class SomeEntityInfo {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;

        @Version
        private Integer version;

        private String status;

        @OneToOne(mappedBy = "someEntityInfo")
        private SomeEntity someEntity;
        [getter/setter]
    }

使用的测试场景

    // create and persist entity and its info object
    em.getTransaction().begin();
    SomeEntity se = new SomeEntity();
    SomeEntityInfo seInfo = new SomeEntityInfo();
    se.setSomeEntityInfo(seInfo);
    seInfo.setSomeEntity(se);

    seInfo.setStatus("status 1");

    em.persist(se);
    em.persist(se.getSomeEntityInfo());
    em.getTransaction().commit();

    // load created entity, modify its info and expect
    // to NOT update the info object while saving the entity again
    em.getTransaction().begin();
    SomeEntity loadedSe = em.find(SomeEntity.class, Integer.valueOf(se.getId()));

    loadedSe.getSomeEntityInfo().setStatus("do not cascade update");

    // as Chris said below, not necessary to explicit save managed entity again
    // em.persist(loadedSe);

    em.getTransaction().commit();

环境

EclipseLink,版本:Eclipse 持久性服务 - 2.5.2.v20140319-9ad6abd

其他信息

规范(http://wiki.eclipse.org/Introduction_to_EclipseLink_JPA_(ELUG)#.40OneToOne)说:

cascade – By default, JPA does not cascade any persistence operations to the target of the association.

事实并非如此(更改是级联的)..我在这里缺少什么?

最佳答案

SomeEntityInfo 实例是托管的,这意味着对其进行的任何更改都将被保存,与级联无关。看看this answer了解更多详情。

关于java - 仅具有 CascadeType.REMOVE 的双向 @OneToOne 保存更改 : that is not wanted,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27169767/

相关文章:

java - 添加新行后未调用 getTableCellRendererComponent

java - 这种 Canvas 绘制方法如何严重降低我的应用程序的速度?

java - 注释反射(使用 getAnnotation)不起作用

java - hibernate 文档: Parent/Child type relationship

java - hibernate 注解,指定列默认值

java - 基于 JPA 2.1 中的多个属性创建转换器

.net - 仅具有 Entity Framework 代码和 ASP.NET MVC 的模块化应用程序

java - 尽管位于 POM 文件中,但 Wiremock 无法用于测试

java - ClassNotFoundException : org. hibernate.service.jndi.JndiException

java - Calendar.HOUR_OF_DAY 始终显示提前 1 小时和 12 小时格式