Hibernate Many to Many and JSON serialization

时间秒杀一切 提交于 2019-12-10 10:40:07

问题


I'm using Hybernate to persist some beans that have a Many-To-Many relationship. Here are the two beans:

Email.java

@Entity
@NamedQuery(name = "Email.findAll", query = "SELECT e FROM Email e")
public class Email implements Serializable {
    private static final long serialVersionUID = 1L;

    //... other fields ...

    // bi-directional many-to-many association to Pratica
    @ManyToMany()
    @JoinTable(name = "email_pratica", joinColumns = {
            @JoinColumn(name = "fk_email_id")
    }, inverseJoinColumns = {
            @JoinColumn(name = "fk_pratica_id")
    })
    private List<Pratica> pratiche;

    public List<Pratica> getPratiche() {
        return this.pratiche;
    }

    public void setPratiche(List<Pratica> pratiche) {
        this.pratiche = pratiche;
    }

}

Pratica.java

@Entity
@NamedQuery(name = "Pratica.findAll", query = "SELECT p FROM Pratica p")
public class Pratica extends AtstTable implements Serializable {
    private static final long serialVersionUID = 1L;

    //... other fields ...

    // bi-directional many-to-many association to Email
    @ManyToMany(mappedBy = "pratiche", fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    private List<Email> emails;

    public List<Email> getEmails() {
        return this.emails;
    }

    public void setEmails(List<Email> emails) {
        this.emails = emails;
    }

}

This works correctly, however the problem is that I then need to serialize/deserialize these beans using JSON. Doing this causes an infinite recursion, since each object Email tries to serialize all of its objects Pratica, which in turn try to serialize all their Emails and so on, until a StackOverflow exception occours.

I've searched online and here on SO, and I've found several solutions to this problem, however none of them work or are applicable, due to the configuration of my project. In particular, here's what I've tried:

Solution 1: using @JsonManagedReference / @JsonBackReference

This seems to be the most suggested solution. However, this only works (as far as I can tell) for One-To-Many or Many-To-One relationships, since the @JsonBackReference annotation does not support collections (Lists, Arrays, Sets, etc.). Or at least, this is what the documentation says and when trying I got an exception that seems to confirm this. I've found a couple of examples online that use this annotation on a List, but for me it didn't work. If anyone has any clue on this, please elaborate.

Solution 2: do not persist one side of the relationship using @JsonIgnore

Adding @JsonIgnore to one of the fields, like this:

@ManyToMany()
@JoinTable(name = "email_pratica", joinColumns = {
        @JoinColumn(name = "fk_email_id")
}, inverseJoinColumns = {
        @JoinColumn(name = "fk_pratica_id")
})
@JsonIgnore
private List<Pratica> pratiche;

breaks the infinite loop, and thus works. It would also suit me, since I don't really need the list of Pratica on the Email objects, I never use it. However, this introduces another big problem: whenever I persist the object back to the database the list of Pratica will be empty (since it was lost during JSON serialization), and thus Hibernate will delete the association record from my Join Table.

Solution 3: using @JsonIdentityInfo
This solution needs Jackson 2.x, but unfortunately, due to restrictions on the server that are beyond my control, I can only use the version of Jackson provided by RESTeasy (resteasy-jackson-provider 2.3.6), which provides a subset of Jackson 1.x

Solution 4: using a custom serializer/deserializer
See solution 3. Even tho the @JsonSerialize/@JsonDeserialize annotations are included in Jackson 1.1, it seems they're not included in the version provided by RESTeasy, or at least the compiler can't find the references, so I assume this is the case.

So, after all this... is there a clean solution to this problem with the restrictions I have? Can it be done in a non-hacky way? And if it can't, what is the "less messy" non-hacky way?


回答1:


You're mixing database objects with json, that's in my opinion the main problem, the main design flaw.

When you want to serialize your data with something other than json, you have to change your persistency layer. If you want to change your persistency layer, you have to change your json stuff, too.

And worse: Let's say you want to unit test your presentation layer - assuming you use json in your frontend - how are you going to do that, without your persistency layer?

So my answer is: Separate your concerns, decouple json from persistency.



来源:https://stackoverflow.com/questions/41260579/hibernate-many-to-many-and-json-serialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!