问题:
我有两个实体,SomeEntity
和 SomeEntityInfo
,它们处于双向一对一关系,仅具有 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/