Как обойти неспособность Джексона обрабатывать прямые ссылки на себя в компонентах JPA - PullRequest
5 голосов
/ 10 марта 2012

Итак, я работаю над API данных RESTful, используя Java, Hibernate, JPA-аннотации, JAX-RS-аннотации, JAXB-аннотации, Jersey и анализатор JSON JSON.

Попробовав различные конфигурации нотаций MAPPING и NATURAL JSON, которые предоставляет Джерси, я наконец решил вместо этого использовать парсер JSON Джексона. Джексон был бы идеален, если бы не этот выпуск ...

Проблема, с которой я столкнулся, заключается в том, что Джексон не работает с аннотациями JAXB, "@XmlID" и "@XmlIDREF", которые я использую для обозначения отношений между сущностями, и хотя "@JsonBackReference" и "@JsonManagedReference помогите с этим. Комбинация, кажется, ломается, когда имеешь дело с прямыми ссылочными свойствами.

Кажется, это будет довольно распространенная проблема. Как кто-нибудь из вас обошел это ограничение с Джексоном?

С моим POJO как ...

@XmlRootElement
public class Employee implements Serializable {
    private Date lastUpdatedOn;
    private Employee lastUpdatedBy;
    private Integer empId;

    @JoinColumn(nullable=false)
    @OneToOne
    @XmlIDREF
    public Employee getLastUpdatedBy() {
        return createdBy;
    }
    public void setLastUpdatedBy(Employee lastUpdatedBy) {
        this.lastUpdatedBy = lastUpdatedBy;
    }

    @Temporal(TemporalType.TIMESTAMP)
    public Date getLastUpdatedOn() {
        return createdOn;
    }
    public void setLastUpdatedOn(Date lastUpdatedOn) {
        this.lastUpdatedOn = lastUpdatedOn;
    }
    @XmlID
    @XmlJavaTypeAdapter(IntegerAdapter.class)
    public Integer getEmpId() {
        return empId;
    }
    public void setEmpId(Integer empId) {
        this.empId = empId;
    }
}

... и следующий EmployeeResource ...

@Path("/Employees")
public class EmployeeResource {
  private List<Employee> employees;

  public List<Employee> getEmployees() {
    return employees;
  }
  public void setEmployees(List<Employee> employees) {
    this.employees = employees;
  }

  @GET
  @Path("/{empId}")
  public Response getEmployees(
    @Context UriInfo ui
    , @PathParam("id") Integer empId
  ) {
    this.employees = HibernateUtil.pagedQuery(
      Employee.class
      , new ArrayList() {
        Restrictions.eq("empId",empId)
      }
    );
    return Response.ok(this).build();
  }
}

Мой ресурс JAX-RS выдаст следующую ошибку

org.codehaus.jackson.map.JsonMappingException: Direct self-reference leading to cycle (through reference chain: resources.EmployeeResource["employees"]->java.util.ArrayList[0]->entities.Employee["lastUpdatedBy"])

... но я хочу, чтобы это произвело ...

{
  "employees" : [ {
    "lastUpdatedOn" : 1331149770737,
    "lastUpdatedBy" : 10150,
    "empId" : 10150,
  } ],
}

Спасибо всем заранее!

ПРИМЕЧАНИЯ:

  1. Я использую IntegerAdapter.class, чтобы преобразовать его в строку, чтобы он работал с аннотацией @XmlID.
  2. Классы Employee и EmployeeResource, описанные выше, являются просто сокращенными версиями моей фактической реализации, но они представляют ту часть моей реализации, которая имеет отношение к этой проблеме прямой самоссылки.

РЕДАКТИРОВАТЬ # 1 2012.03.10 Извините, в моей первой версии этого вопроса я запутался между версией, которую я использую, используя естественную запись Джерси, и версией, которую я использовал с Джексоном. Я пересмотрел свой вопрос, чтобы более точно отразить проблему прямой самореференции, которую я имею с Джексоном.

1 Ответ

4 голосов
/ 12 марта 2012

Jackson 1.x не имеет специальной поддержки для разрешения циклических ссылок, но есть поддержка для обработки зависимостей родительского / дочернего стиля: эта запись в блоге имеет больше информации.

Jackson 2.0 будет иметь поддержку произвольной обработки идентификаторов объектов / ссылок, используя новую аннотацию @JsonIdentityInfo, так что, возможно, это можно использовать для решения проблемы. Официальный релиз 2.0 еще не вышел, но кандидаты на выпуск (последний из которых RC2) есть, на случай, если вы захотите посмотреть. Не уверен, что это решит вашу проблему, но, возможно, это поможет.

РЕДАКТИРОВАТЬ: На самом деле, модуль аннотации Jackson JAXB будет иметь поддержку @XmlID / @XmlIDREF для 2.0.0 - это только что реализовано, см. здесь .

...