双向@ManyToMany的JSON映射的无限递归

时间:2015-12-19 21:26:34

标签: java hibernate jpa orm

我有以下情况:有公司和员工。每家公司都有一组员工。每位员工都可以为多家公司工作。所以我实现了以下关系:

Company.class:

@JoinTable(name = "company_employee", joinColumns = @JoinColumn(name = "company_id") , inverseJoinColumns = @JoinColumn(name = "employee_id") )
@ManyToMany(fetch = FetchType.LAZY)
private Set<Employee> employees;

Employee.class:

@JoinTable(name = "company_employee", joinColumns = @JoinColumn(name = "employee_id") , inverseJoinColumns = @JoinColumn(name = "company_id") )
@ManyToMany(fetch = FetchType.EAGER)
private Set<Company> companies;

目标是能够抓取List<Employee>,每位员工使用Set<Company>或其他方案来抓取List<Company>,但不提取相关的Set<Employee>。但是,如果我按ID获取Company,则还应提取相关的Set<Employee>

我在daos中做了什么: 如果我在两种情况下都获取Lists,那么它可以正常工作而不会出现问题:什么是渴望 - 获取,什么是懒惰 - 不被提取。 要按ID获取Employee,我会执行以下操作,并且它会提取一个非空Set<Company>的Employee,正如我所期望的那样:

public Employee find(Long id) {
        Employee employee = entityManager.find(Employee.class, id);
        return employee;

要按ID而不是空Set<Employee>来获取公司,我试过了:

变体1:

public Company find(Long id) {
        TypedQuery<Company> query = em.createQuery("select distinct e from Company e left outer join fetch e.employees where e.company_id=:company_id", Company.class);
        query.setParameter("company_id", id);
        Company company = query.getSingleResult();
        return company;
    }

VARIANT2:

 public Company find(Long id) {
            Company company = entityManager.find(Company.class, id);
            Hibernate.initialize(company.getEmployees());
            return company;
        }

正如我所看到的,由于JSON序列化期间的无限递归,variant1和variant2都给出了org.springframework.http.converter.HttpMessageNotWritableException。 我尝试使用@JsonManagedReference@JsonBackReference,然后使用@JsonBackReference设置注释永远不会获取我使用的任何join fetchHibernate.initialize。 那么实现我需要的正确方法是什么?谢谢。

1 个答案:

答案 0 :(得分:1)

我似乎找到了一个解决方案:使用@JsonIdentityInfo。更多信息here 现在我的实体看起来像那样(删除了所有不相关的字段和方法),它们完全按照我的需要工作:

Company.class:

@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="company_id")
public class Company {
     @JoinTable(name = "company_employee", joinColumns = @JoinColumn(name = "company_id") , inverseJoinColumns = @JoinColumn(name = "employee_id") )
     @ManyToMany(fetch = FetchType.LAZY)
     private Set<Employee> employees;
}

Employee.class:

 @Entity
 @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="employee_id")
 public class Employee {
     @JoinTable(name = "company_employee", joinColumns = @JoinColumn(name = "employee_id") , inverseJoinColumns = @JoinColumn(name = "company_id") )
     @ManyToMany(fetch = FetchType.EAGER)
     private Set<Company> companies;
 }

我希望它会对某人有所帮助。

更新1 实际上,正如尼尔斯托克顿所注意到的那样,映射不太正确,并且不是合法的双向。所以我只是改变了下面的一个实体,然后没有额外的注释来避免无限递归

     @Entity
     public class Employee {
         @ManyToMany(fetch = FetchType.EAGER, mappedBy="employees")
         private Set<Company> companies;
     }

我认为这是重要的更新。