如果之前已经回答过这个问题,我想提前道歉。
请注意,该项目使用的是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 question。但是首先它首先发送一个select查询来填充Member对象。但这意味着在保存记录之前,我必须请求另一个select语句。这有点开销,不是吗?
更新 我在构造函数中添加了这段代码:
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。
答案 0 :(得分:0)
请尝试使用具有Model
和Product
持久性的简单控制台应用程序来学习Hibernate。对@JoinColumn
products
但@OneToMany
mappedBy
属性Member
,您不需要Product
。您可以将User称为Product
,将UserFriend称为User
。在每个config
中,您需要拥有<connectionStrings>
<add name="myConnectionString" connectionString="server=ServerAddress;database=myDb;uid=myUser;password=myPass;" />
</connectionStrings>
的外键 - 将产品添加到成员this way。对于实验,您可以使用this或this。
答案 1 :(得分:0)
好的,所以我终于让它工作了。我不知道在哪里查明,但我绝对可以说杰克逊问题不是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。如果使用@Id注释mobileNum或任何外键,Hibernate将正确绑定它并且不会在保存对象时出现任何问题。
但是如果外键没有用@Id,Hibernate注释(即使Jackson已经正确地将JSON映射到对象),它也不会正确绑定它,导致空值。 Google搜索关键字:对象引用未保存的瞬态实例
在我看来,添加Cascade并不是一个好的解决方案,因为它只会在Member类中创建更多记录。如果记录已存在,它将继续创建EVEN! (尝试在mobileNum上设置一个唯一约束并删除@Id注释。
总的来说,本周Hibernate真的把我烧了。如果您是具有优化现有SQL经验并且只想将其转换为代码的开发人员,请远离Hibernate。使用MyBatis,即使它有很多样板,用手工创建SQL比用Hibernate更令人满意。