繁体   English   中英

如何使用Jackson作为外键使用Hibernate作为持久性保存对象?

[英]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。

我发布的类似问题的另一个链接

请尝试使用带有ModelProduct持久性的简单控制台应用程序学习Hibernate。 你不需要@JoinColumnproducts ,但@OneToManymappedBy属性。 您可以将User称为Member的类似物,并将UserFriend称为Product 在每个Product您都需要User外键-以这种方式将产品添加到成员。 对于实验,您可以使用thisthis

好吧,我终于要使它工作了。 我不知道确切的位置,但是我可以肯定地说这不是由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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM