使用Jackson和Hibernate的多对多无限递归

时间:2015-12-16 05:20:34

标签: java mysql json hibernate recursion

由于多对多关系的循环引用而获得以下错误。

org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError)

我尝试过使用 @JsonIdentityInfo @ com.fasterxml.jackson.annotation.JsonIgnore @JsonManagedReference ,但这些都不适用于我。我使用的是lombok,因此是@ getter / setter。

用户表

@Entity
@Table(name = "user")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="user_id", scope=User.class)
public class User implements Serializable{

    @Getter
    @Setter
    @Id
    @GeneratedValue(strategy = IDENTITY, generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    public int user_id;

    @JsonManagedReference
    @Getter
    @Setter
    @com.fasterxml.jackson.annotation.JsonIgnore
    @ElementCollection(targetClass=UserInterest.class)
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.user", cascade=CascadeType.ALL)
    public Set<UserInterest> userInterestSet = new HashSet<UserInterest>();
}

兴趣表

@Entity
@Table(name = "interest")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="interest_id", scope=Interest.class)
public class Interest implements Serializable{

    @Getter
    @Setter
    @Id
    @GeneratedValue(strategy = IDENTITY, generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    public int interest_id;

    @Getter
    @Setter
    @Column(name = "interest_name", nullable = false, length=100)
    public String interest_name;

    @Getter
    @Setter
    @com.fasterxml.jackson.annotation.JsonIgnore
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.interest", cascade=CascadeType.ALL)
    public Set<UserInterest> userInterestSet = new HashSet<UserInterest>();
}

UserInterest联接表

@Entity
@Table(name="user_interest")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="pk", scope=UserInterest.class)
@AssociationOverrides({
        @AssociationOverride(name="pk.user", joinColumns=@JoinColumn(name="user_id")),
        @AssociationOverride(name="pk.interest", joinColumns=@JoinColumn(name="interest_id"))
})
public class UserInterest implements Serializable {
    @Getter
    @Setter
    @com.fasterxml.jackson.annotation.JsonIgnore
    @GeneratedValue(generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    public int user_interest_id;

    @EmbeddedId
    @Getter
    @Setter
    @com.fasterxml.jackson.annotation.JsonIgnore
    public UserInterestId pk;

    @Transient
    @Getter
    @Setter
    @com.fasterxml.jackson.annotation.JsonIgnore
    public User user;

    @Transient
    @Getter
    @Setter
    @com.fasterxml.jackson.annotation.JsonIgnore
    public Interest interest;
}

UserInterestId类

@Embeddable
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=UserInterestId.class)
public class UserInterestId implements Serializable{
    @Getter
    @Setter
    @org.codehaus.jackson.annotate.JsonIgnore

    @ManyToOne(fetch = FetchType.LAZY)
    @com.fasterxml.jackson.annotation.JsonIgnore
    @JsonBackReference
    public User user;

    @Getter
    @Setter
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="interest_id")
    @ManyToOne(fetch = FetchType.LAZY)
    @com.fasterxml.jackson.annotation.JsonIgnore
    @JsonBackReference
    public Interest interest;
}

当我在加入的User对象上运行以下内容时,我收到错误:

ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
ow.writeValueAsString(userSet);

我对 Hibernate 非常陌生,所以我们非常感谢任何指针。我已经阅读了5-10篇SO文章,这些文章提出了我上面提到的解决方案,但我仍然无法停止循环引用。万分感谢!

2 个答案:

答案 0 :(得分:0)

你应该解开你的对象。来自here

的示例
@SuppressWarnings("unchecked")
protected T unproxy(T entity){
    if (entity == null) {
        return null;
    }

    if (entity instanceof HibernateProxy) {
        try {
            Hibernate.initialize(entity);
        } catch (ObjectNotFoundException e) {
            return null;
        }
        entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
    }
    return entity;
}

或者这样(来自here

public <P> List<P> unproxy(Collection<P> objects) {
    Session session = sessionFactory.getCurrentSession();
    List<P> result = new ArrayList<P>();
    for (P t : objects) {
        Object unproxied = ((SessionImplementor)session).getPersistenceContext().unproxy(t);
        result.add((P) unproxied);
    }
    return result;
}

答案 1 :(得分:0)

找到解决方案。对于我的ObjectWriter / ObjectMapper,我切换到com.fasterxml.jackson.databind.ObjectWriter / Mapper而不是codehaus。似乎jsonIgnore和JsonIdentityInfo并没有得到codehaus.jackson.map的承认,​​或者至少不是我的版本。