2015-02-23 211 views
1

我有USER(id)和CONTACT(user_id,first,last)表。 CONTACT.user_id是USER表的外键。SpringDataJPA通过主键/外键保存OneToOne关系,保存对象

在User.java:

@Id 
@GeneratedValue(strategy=GenerationType.IDENTITY) 
private Integer id; 

@OneToOne(cascade = CascadeType.ALL) 
@PrimaryKeyJoinColumn 
private Contact contact; 

在Contact.java

@Id 
@Column(name="USER_ID") 
private Integer userId; 

@MapsId 
@OneToOne(mappedBy = "contact") 
@JoinColumn(name = "USER_ID") 
private User user; 

我使用userRepository.saveAndFlush(用户),以节省用户对象。由于我在CONTACT中使用USER.ID作为外键,因此我需要在CONTACT之前插入USER,但JPA首先插入CONTACT,它将CONTACT视为USER的成员。所以当插入CONTACT时,我得到一个USER_ID不能为NULL错误。我应该如何解决这个插入的顺序?或者我应该通过共享主键来避免使用OneToOne映射?

谢谢!

+0

[SpringDataJPA保存OneToOne关系获取可能的重复无法添加或更新子行:外键约束失败](http://stackoverflow.com/questions/28683427/springdatajpa-save-onetoone-relationship-getting-cannot -add-or-update-a-child-ro) – jfun 2015-02-23 23:38:41

回答

2

我有USER(id)和CONTACT(id,first,last)表。 CONTACT.user_id是 USER表的外键

通过作出这个声明,我会说,这种关系然后不是与共享主键一对一的关系。如果是这种情况,我希望表格结构如下。

USER(id) 
CONTACT(id, first, last) 

作为替代使用@OneToOne,你可以考虑使用@SecondaryTable即地图横跨两个表的用户实体:这似乎是一个更自然的适合的模型。

http://en.wikibooks.org/wiki/Java_Persistence/Tables#Multiple_tables

无论如何,不​​管,如果你想使用@OneToOne然后如API文档中的两个在下面给出

一例中的一对一个协会,假定两个来源和 目标共享相同的主键值。

http://docs.oracle.com/javaee/6/api/javax/persistence/OneToOne.html

在此之后,我会说的映射应如下:

public class User{ 

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

    @OneToOne(mappedBy ="user", cascade =CascadeType.ALL) 
    private Contact contact; 
} 

public class Contact{ 

    @Id 
    private Long id; 

    @OneToOne 
    @MapsId 
    @JoinColumn(name = "user_id") 
    private User user; 
} 
+0

MapsId通知JPA在引用的Contact实例的userId字段中使用的值应该用于设置User.id属性中的值。排序需要放在Contact.userId字段才能生效,否则它将始终为空(除非由应用程序手动设置)。 – Chris 2015-02-24 14:00:39

+1

我提出的映射实际上是错误的方法。我已经测试了更新的映射,没有任何问题在MySQL上。 – 2015-02-24 18:02:19

0

这个问题似乎是,你有User.contact关系设定为控制关系 - 你已将Contact.user关系标记为都映射到联系人映射以及指定错误的joinColumn。 Contact.user关系中的这些设置发生冲突,因此只能使用一个,并且mappedBy实质上表明外键字段由User.contact关系控制,从而强制您看到的插入顺序。

开关周围的映射会给你你在找什么:

public class User{ 
    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Integer id; 

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL) 
    private Contact contact; 
} 

public class Contact{ 
    @Id 
    private Integer userId; 

    @MapsId 
    @OneToOne() 
    @JoinColumn(name = "USER_ID") 
    private User user; 
} 

上述映射指定的USER_ID是一个外键User.ID领域,都会用到用户这个关系。联系人和Contact.user关系。 MapsId将允许Contact.user关系也设置联系人。一旦在引用的User实例中设置了userId值。