@OnetoOne关系如何在JPA中发挥作用?

时间:2014-11-26 22:39:58

标签: spring jpa one-to-one

我正在尝试在两个实体之间建立一对一的映射。一个实体维护用户记录如下:

@Entity
public class ConcreteUser implements User{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;
    private String email;
    private int age;
    private SEX sex;
    private String accessLevel;

    public ConcreteUser() {
    }

    public ConcreteUser(String name, String email, int age, SEX sex, String accessLevel) {
        // set class properties
    }

   //
   // Some getter and setter code
   //

我想使用上述实体中的主键作为其他实体中的外键,它维护其他信息。这是另一个实体的样子:

@Entity
public class SomeOtherEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "SOME_COLUMN_NAME")
    private long recordId;

    //
    // some other private fields here
    //

    @OneToOne(cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private ConcreteUser concreteUser;

    public SomeOtherEntity () {
    }

    // getters and setters etc

我的示例测试用例如下:

@Test
public void testAddSomeOtherEntity() throws Exception {


    /* This is the user, whose primary key will be used as a foreign key in SomeOtherEntity */
    ConcreteUser user = new ConcreteUser(...);


    /* Create a new SomeOtherEntity and assign a ConcreteUser to it */
    SomeOtherEntity d = new SomeOtherEntity();
    d.setConcreteUser(user); /* I doubt if this line has any effect at all */

    // add SomeOtherEntity to table
    /* addSomeOtherEntity is translated to an HTTP request and server responds with added entity  */
    d = myService.addSomeOtherEntity(d); 
    assertNotNull(d);

    /* At this point, the recordId is generated and updated */

    // Check if this entity was added properly
    long recordId = d.getRecordId();
    SomeOtherEntity d2 = myService.getSomeOtherEntityById(recordId);
    assertNotNull(d2);

    /* This test case passes */
    assertEquals(d2.getRecordId(), d.getRecordId()); 

    /* But this test case fails */
    assertEquals(d2.getConcreteUser().getId(), d.getConcreteUser().getId());

}

总之,我创建了SomeOtherEntity对象,分配了一个ConcreteUser对象并保留了SomeOtherEntity。但是,当我重新检索SomeOtherEntity时,我获得了与之前分配的不同的ConcreteUser。特别是,我得到的ConcreteUser,与" idI;#34;具有相同的" id"。这不是我所期待的。

我对Spring很新,我确信我误解了一些东西。截至目前,我正在考虑事先将ConcreteUser分配给SomeOtherEntity意味着什么。相反,也许我应该首先创建并持久化SomeOtherEntity,然后更新ConcreteUser? 如果有人可以提供一些建议以及它在现实世界中的表现如何,我真的很感激。提前致谢。

2 个答案:

答案 0 :(得分:0)

在SomeOtherEntity中,为ConcreteUser指定@PrimaryKeyJoinColumn映射。如果您选中the documentation of the annotation,就会发现它说:

  

...它可以在OneToOne映射中使用,其中主键是   引用实体用作引用的外键   实体

这意味着SomeOtherEntity的主键值用作ConcreteUser的外键值。

您想要使用@JoinColumn注释。

答案 1 :(得分:0)

因此,事实证明,在Spring中实现一对一关系有不同的方法。以下是对不同方式的简短而有用的介绍: Hibernate one-to-one mapping using annotations

这里的问题不是拥有方,而是从三者中选择一对一的方法。根据上面提到的文章,当您希望两个表的主键匹配时,使用@PrimaryKeyJoinColumn注释,这不是这里的情况。 如问题所述,测试用例失败,因为Hibernate根据主键映射了两个表,而不是使用ConcreteUser

分配了setConcreteUser实体。