Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate合并问题与一对一映射_Java_Hibernate_Jpa 2.0 - Fatal编程技术网

Java Hibernate合并问题与一对一映射

Java Hibernate合并问题与一对一映射,java,hibernate,jpa-2.0,Java,Hibernate,Jpa 2.0,我在Hibernate(3.5.6最终版)中使用JPA2.0- @Entity @Inheritance(strategy = InheritanceType.JOINED) public abstract class A{ private Long id; @OneToOne @JoinColumn(name = "foo_id", nullable = false) private Foo foo; ... } @Entity @PrimaryK

我在Hibernate(3.5.6最终版)中使用JPA2.0-

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class A{
    private Long id;

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

@Entity
@PrimaryKeyJoinColumn(name = "B_ID")
public class B{
        ...
}

@Entity
@PrimaryKeyJoinColumn(name = "C_ID")
public class C{
        ...
}
Foo
实体是-

@Entity
public class Foo{
    @Id
    private Long id;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "foo")
    private A a

    // getters / setters omitted    
}
现在,我将引用
B
的实体
Foo
保存到字段“a”。稍后,我想用类
C
将Foo的实例更新为属性“a”,所以我所做的是-

loadedFooInstance.setA(new C());
entityManager.merge(loadedFooInstance);
但我注意到的是,在分配C之前,它不会删除分配给该Foo对象的原始B对象。因此,在分配新实例之前,我需要手动删除分配给该Foo实例的A的所有引用
但是我相信hibernate一定有办法处理这样的场景,我在映射中遗漏了一些东西。
我的地图有什么问题吗。。或者这种映射可以更好地实现,所以我不需要处理这种手工工作。

您的OneTONE关系由A方管理,而不是由Foo方管理。因此,您需要更改A端的关系(因为hibernate只关注管理关系的一端)

另一种方法是更改管理关系的一方:

public abstract class A{
   ...
   @OneToOne(mappedBy = "a") 
   private Foo foo;
   ...
}

public class Foo{
    ...
    @OneToOne
    @JoinColumn(name = "a_id",  nullable = false)
    private A a
    ...
 }

但这也会改变你的数据库布局

此模式中的某些内容不正确。当您删除B时,您希望删除Foo,因此A是关系的拥有方。所以如果没有B的存在,Foo就不应该存在。但是你现在所做的是从Foo中删除B,因此违反了关系,因为现在没有B。你应该遵循拉尔夫的建议2。建议#1行得通,但显然富应该是拥有方。而级联也将从映射的旁边工作。您定义的关系不正确

编辑:

要将Foo中的现有B设置为C: 这几乎与拉尔夫早期的建议相似


我不想更改数据库布局。。因为我想应用删除级联。。因此,如果Foo被删除,那么A必须自动删除。在第二个选项中,不可能应用这样的删除级联,对吗?@Premraj M:对于第二个场景:您可以将cascade=CascadeType.ALL-on应用到Foo.a.-我不知道它在mappedBy方面是否有效,但我不想在Foo中保留A的Id,因此如果HQL删除了Foo,那么A应该自动删除(在DB端使用delete cascade)。。现在有这样的映射有意义吗?@Premraj M:Summary:每个hibernate关系都有两个方面:一个是维护关系的方面,另一个是“只读”的方面,每个关系都有一个存储foraign键的方面,另一个方面(由映射)。通常,关系维护端和密钥存储端是相同的。-您可以通过设置“反向”标志使非存储端变为维护端,并将存储端设置为只读(update=false,insert=false)但是我不知道级联删除从“mapped by”端到“foraign key”端都是有效的。@Premraj M:但是根据我的经验,更改维护端通常会导致问题,所以不要一直这样做,因为你并不真正需要它。并为这种关系编写一系列测试用例如果你有更多的问题,那么问一个新问题,因为所有这些都超出了这个问题的范围。不。。当我删除Foo时,我想删除与Foo相关的B或C。。这有意义吗?或者您可以提供示例来定义与此要求的关系。@Premraj M-然后您应该显式地从foo中删除A的所有关联实例,然后在新的A实例中设置foo并持久化。这是必需的,因为您不能从A端对Foo应用cascade all,否则,删除A也会删除Foo。请参见编辑。@Premraj M-旧的A instance即B从未从数据库中删除,我认为它不应该存在于数据库中。此外,还必须保存C或在foo上执行级联合并操作。
public abstract class A{
   ...
   @OneToOne(mappedBy = "a") 
   private Foo foo;
   ...
}

public class Foo{
    ...
    @OneToOne
    @JoinColumn(name = "a_id",  nullable = false)
    private A a
    ...
 }
Foo foo = entityManager.find(Foo.class, id);
B b = foo.getA();
entityManager.remove(b); //Explicitly remove or B still remains in database as B is the owning side
C c = new C();
c.setFoo(foo);
entityManager.persist(c);  //c is the owning side, hence save c and not foo
entityManager.refresh(foo);