2015-11-17 63 views
1

我使用PlayFramework 2.3和我有以下类:为什么JPA不更新OneToOne关系上的外键?

MyEntity.java:

@Entity(name = "myentity") 
public class MyEntity extends Model { 
    @Id 
    @GeneratedValue 
    public long id; 

    @OneToOne(cascade = CascadeType.ALL, optional = true) 
    @JoinColumn(name = "actual_version_id", nullable = true) 
    public Version actualVersion; 

    @OneToOne(optional = true) 
    @JoinColumn(name = "next_version_id", nullable = true) 
    public Version nextVersion; 

    ... 
} 

Version.java

@Entity(name = "version") 
public class Version extends Model { 
    @Id 
    @GeneratedValue 
    public long id; 

    @OneToOne 
    @JoinColumn(name = "entity_id", nullable = false) 
    public MyEntity entity; 

    ... 
} 

,当我想,以便为新版本实体,我通过detach复制它,将id设置为0,并且像这样坚持:

public Version clone(){ 
    JPA.em().detach(this); 
    this.id = 0; 
    JPA.em().persist(this); 
    return this; 
} 

如果我使用下面的代码它工作正常(第一码)

entity.nextVersion = entity.actualVersion.clone(); 
    JPA.em().flush(); 
    entity.actualVersion = entity.nextVersion; 
    entity.nextVersion = null; 
    JPA.em().flush(); 

我真的不喜欢这个代码,因为我可以这样使用它(第二码)

entity.actualVersion = entity.actualVersion.clone(); 
    JPA.em().flush(); 

但如果我这样做外键不更新在'实体'表中,我不知道为什么。任何人都可以告诉我两种实施克隆的区别吗?这对我来说似乎是一些JPA黑魔法,但我找不到答案。

编辑:

这是一个重构的代码,以使其更易于已了解。我不覆盖任何Object类或其他任何函数(我的clone()函数在原始代码中被称为newRound,例如带有2个参数)

我并不真正想让任何模型修改将CascadeType.ALL添加到注释或类似的东西中,因为这是一个现在正在生产的程序,我不知道会产生什么样的错误。

我只想知道为什么第一个代码更新实体中的外键(actual_version_id),而第二个代码没有。我认为它必须与actualVersion变量中的CascadeType.ALL注释参数一致。

+0

您是否在持续期间设置了级联对象写入? –

+0

我真的不明白你的问题。通过设置级联对象写什么意思? – aBnormaLz

+1

我确定它是JPA提供程序实现的依赖,但是......我想说的是,在身份为提供程序管理的实体('@ GeneratedValue')上操纵密钥值是一方的犯规。 – scottb

回答

1

在JPA设置中对clone()要非常小心; JPA环境通常会将跟踪属性添加到类的字节码中,并可能会感到困惑。相反,请覆盖默认clone()以创建一个实际对象并逐个手动复制所有属性。