【发布时间】:2014-11-27 11:34:53
【问题描述】:
问题:
我有两个实体,SomeEntity 和 SomeEntityInfo,它们是双向一对一关系,只有 CascadeType.REMOVE 级联集。
如果 SomeEntity.someEntityInfo 已更改,并且 SomeEntity 已(已存在)保存 -> 不应发生对 SomeEntityInfo 表/对象的级联数据库更新。
但是,相关实体也会更新
编辑/更新
换句话说:我希望SomeEntityInfo 是“(有点)不可变的”。它应该在创建 SomeEntity 时创建,但不更新/检查版本 - 乐观锁定 - 如果重新保存 SomeEntity。
到目前为止我做了什么
-
在
SomeEntity的getter 中返回SomeEntityInfo的副本会导致通过未标记为 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 Persistence Services - 2.5.2.v20140319-9ad6abd
其他信息
规范 (http://wiki.eclipse.org/Introduction_to_EclipseLink_JPA_(ELUG)#.40OneToOne) sais:
cascade – 默认情况下,JPA 不会将任何持久性操作级联到关联的目标。
事实并非如此(更改是级联的)..我在这里缺少什么?
【问题讨论】:
标签: java jpa orm eclipselink