使用hibernate进行一对一参照完整性 [英] Referential integrity with One to One using hibernate

查看:120
本文介绍了使用hibernate进行一对一参照完整性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两张表 -


Foo {foo_id,name}

Foo_properties {fp_id,foo_id,phoneNumber}

>
现在我想使用hibernate将其映射到我的对象模型中。
我需要foo_properties中的foo_id,因为我想维护引用完整性并希望添加ON DELETE CASCADE约束。

所以我用下面的方式映射关系 -

  @Entity 
public class Foo {
@Id
private long foo_id;

私人字符串名称;

@OneToOne(mappedBy =foo)
private FooProperties fooProperties;
}

@实体
公共类FooProperties {

@Id
私人长fp_id;

private String phoneNumber;

@OneToOne
@JoinColumn(name =foo_id,nullable = false)
private Foo foo;



$ b现在既然拥有FooProperties类,我会面临以下问题 -


如果我将FooProperties的新实例设置为Foo,则现有FooProperties仍保留在数据库中,而hibernate不会删除该实例,例如



  Foo foo = entityManager.find(Foo.class,fooId); 
foo.setFooProperties(new FooProperties(xxx-xxx-xxx));
entityManager.merge(foo);

结果与FooProperties表中的新行一起存在。现在我不明白我如何改变我的映射,所以我可以有上面的代码(或它的变体)适用于所有场景,这意味着我需要Foo作为拥有者和FooProperties中的foo_id。有没有办法像这样定义映射?



注意:我已经问过
在这个基础上映射这个onetoone-in-hibernate-using-jpa>问题
/ code>。但是,由于解释JPA规范中的casuistics,它不会像预期的一对一关系那样工作( orphanRemoval
的正确行为。 >使用以下技巧:

  @Entity 
public class Foo {
@OneToMany(mappedBy = foo,orphanRemoval = true)
private List< FooProperties> fooProperties;
$ b $ public FooProperties getFooProperties(){
if(fooProperties == null || fooProperties.isEmpty())return null;
else返回fooProperties.get(0);

$ b $ public void setFooProperties(FooProperties newFooProperties){
if(fooProperties == null)fooProperties = new ArrayList< FooProperties>();
else fooProperties.clear();
if(newFooProperties!= null)
fooProperties.add(newFooProperties);
}
...
}

@实体
公共类FooProperties {
@ManyToOne
@JoinColumn(name = foo_id,可为空= false)
private Foo foo;
...
}

甚至如果你不这样做需要 FooPropeties.foo

  @Entity 
public class Foo {
@OneToMany(orphanRemoval = true)
@JoinColumn(name =foo_id,nullable = false)
private List< FooProperties> fooProperties;

// getter / setter as above
...
}


I'm having two tables -

Foo { foo_id, name }
Foo_properties { fp_id, foo_id, phoneNumber}

Now I want to map this in my object model using hibernate.. I need a foo_id in Foo_properties because i want to maintain referential integrity and want to add ON DELETE CASCADE constraint.
so I mapped the relation in the following way -

@Entity
public class Foo{
    @Id
    private long foo_id;

    private String name;

    @OneToOne(mappedBy = "foo")
    private FooProperties fooProperties;
}

@Entity
public class FooProperties{

    @Id
    private long fp_id;

    private String phoneNumber;

    @OneToOne
    @JoinColumn(name = "foo_id",  nullable = false)
    private Foo foo;
}

Now since the owning side is FooProperties class, I'm facing following issues -

If I set the new instance of FooProperties to Foo the existing FooProperties still remains in DB and hibernate doesn't delete that instance, e.g.

Foo foo = entityManager.find(Foo.class, fooId);
foo.setFooProperties(new FooProperties("xxx-xxx-xxx"));
entityManager.merge(foo);

This results into the new row in FooProperties table along with the existing one. Now I don't understand how I can change my mapping to so I can have above code (or variant of it) working for all scenarios, that means I need Foo as a owning side and foo_id in FooProperties. Is there any way to define the mapping like this?

NOTE: I already asked question based on this but I think I wasn't clear in previous question so asked this another one.

解决方案

You were already told to use orphanRemoval = true or CascadeType.DELETE_ORPHAN. However, due to casuistics in interpretation of JPA Specification it wouldn't work as expected for one-to-one relationships (HHH-5559).

You can achieve a proper behaviour of orphanRemoval with the following trick:

@Entity
public class Foo{
    @OneToMany(mappedBy = "foo", orphanRemoval = true)
    private List<FooProperties> fooProperties;

    public FooProperties getFooProperties() {
        if (fooProperties == null || fooProperties.isEmpty()) return null;
        else return fooProperties.get(0);
    }

    public void setFooProperties(FooProperties newFooProperties) {
        if (fooProperties == null) fooProperties = new ArrayList<FooProperties>();
        else fooProperties.clear();
        if (newFooProperties != null)
            fooProperties.add(newFooProperties);            
    }
    ...
}

@Entity
public class FooProperties{
    @ManyToOne
    @JoinColumn(name = "foo_id",  nullable = false)
    private Foo foo;
    ...
}

Or even this, if you don't need FooPropeties.foo:

@Entity
public class Foo{
    @OneToMany(orphanRemoval = true)
    @JoinColumn(name = "foo_id",  nullable = false)        
    private List<FooProperties> fooProperties;

    // getter/setter as above
    ...
}

这篇关于使用hibernate进行一对一参照完整性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆