[英]How to save an object, using Hibernate as persistence, with a foreign key using Jackson?
如果您已经回答了这个问题,我想向您道歉。
请注意,该项目正在使用Spring Boot,Jackson和Hibernate。
无论如何,我分叉了Jasenko Hadziomeragic的一个项目。 我想知道他如何在Jasenko的项目Product对象中保存对象。 在此项目中,Product对象如下所示(请注意,我删除了部分代码以专注于外键):
@JoinColumn(name = "member_id")
@NotNull
private Long member_id;
我可以使用以下JSON保存新记录:
{
"name" : "Product 2",
"member_id" : "1"
}
这行得通,但从我在互联网上搜索到的内容来看,最好改用以下方法:
public class Product {
@ManyToOne()
@JoinColumn(name="member_id")
private Member member;
/* A getter/setter for the memeber id*/
public Long getMember_id() {
return this.member.getId();
}
public void setMember_id(Long member_id) {
this.member.setId(member_id);
}
}
我试图用上面的json保存新记录,但出现此错误:
java.lang.NullPointerException: null
at com.jersey.representations.Product.setMember_id(Product.java:100)
这是指向我的github的链接,其中包含修改后的代码。
我还检查了与我所关心的类似的SO问题 。 但是首先要执行的操作是先发送选择查询以填充Member对象。 但这意味着在保存记录之前,我必须请求另一个select语句。 这有点开销,不是吗?
UPDATE我在构造函数中添加了以下代码:
public Product() {
this.member = new Member();
}
我确实解决了问题,但这是解决我的担忧的正确方法吗?
更新2
我要避免的是发送此JSON:
[
{
"id": 1,
"name": "Derp",
"currency": "599",
"regularPrice": 1203,
"discountPrice": 59,
"member": {
"id": 1,
"firstName": "Paul",
"lastName": "Andrews",
"email": "myemail@email.com"
}
},
{
"id": 2,
"name": "Another product ",
"currency": "909",
"regularPrice": 1203,
"discountPrice": 59,
"member": {
"id": 1,
"firstName": "Paul",
"lastName": "Andrews",
"email": "myemail@email.com"
}
},
{
"id": 3,
"name": "Another product 1",
"currency": "909",
"regularPrice": 1203,
"discountPrice": 59,
"member": {
"id": 1,
"firstName": "Paul",
"lastName": "Andrews",
"email": "myemail@email.com"
}
}
]
如您所见,成员不断重复,而我只能发送memberId。
请尝试使用带有Model
和Product
持久性的简单控制台应用程序学习Hibernate。 你不需要@JoinColumn
的products
,但@OneToMany
用mappedBy
属性。 您可以将User称为Member
的类似物,并将UserFriend称为Product
。 在每个Product
您都需要User
外键-以这种方式将产品添加到成员。 对于实验,您可以使用this或this 。
好吧,我终于要使它工作了。 我不知道确切的位置,但是我可以肯定地说这不是由Jackson问题编组的JSON。
这是我的解决方案:
首先,我找不到解决方案,而是将其添加到具有外键的类中:
@Entity
public class Product {
public Product() {
this.member = new Member();
}
@ManyToOne()
@JoinColumn(name="blargh")
private Member member;
/** Jackson can't instantiate and object automatically so you have to help it **/
/** By creating the object right after Product is initialzed by some other code **/
public Long getMobileNum() {
return this.member.getMobileNum();
}
public void setMobileNum(Long mobileNum) {
this.member.setMobileNum(mobileNum);
}
}
下一步在另一个类中查找Id注释。
@Entity
public class Member {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Id
private Long mobileNum;
}
我故意使注释错误以证明观点。 在Product类中,将其链接到Member类的外键是mobileNum。 如果mobileNum或任何外键都带有@Id注释,则Hibernate将正确绑定它,并且在保存对象时不会有任何问题。
但是,如果未使用@Id,Hibernate注释外键(即使Jackson正确地将JSON映射到对象), 它将无法正确绑定它,从而导致null值 。 Google搜索关键字:对象引用了未保存的临时实例
我认为添加Cascade并不是一个好的解决方案,因为它只会在Member类中创建更多记录。 如果记录已经存在,它将继续创建EVEN! (尝试对mobileNum施加唯一约束,并删除@Id注释。
总的来说,这周在休眠状态真的让我很疲惫。 如果您是具有优化现有SQL经验的开发人员,并且只想将其转换为代码,请远离Hibernate。 使用MyBatis,即使它有很多样板,手动创建SQL也比使用Hibernate令人满意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.