我有两个Java类:Usuario和Entrada。

乌苏里奥:

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

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int idusuario;

    private String apellido1;

    private String apellido2;

    private String email;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="fecha_alta")
    private Date fechaAlta;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="fecha_baja")
    private Date fechaBaja;

    @Column(name="is_admin")
    private boolean isAdmin;

    private String nombre;

    private String password;

    //bi-directional many-to-one association to CompraEntrada
    @OneToMany(mappedBy="usuarioBean")
    @JsonIgnore
    private List<CompraEntrada> compraEntradas;

    //bi-directional many-to-one association to Entrada
    @OneToMany(mappedBy="usuarioBean")
    private List<Entrada> entradas;

    //bi-directional many-to-one association to Evento
    @OneToMany(mappedBy="usuario")
    @JsonIgnore
    private List<Evento> eventos;

    //bi-directional many-to-one association to Mensaje
    @OneToMany(mappedBy="emisor")
    @JsonIgnore
    private List<Mensaje> mensajesEmitidos;

    //bi-directional many-to-one association to Mensaje
    @OneToMany(mappedBy="receptor")
    @JsonIgnore
    private List<Mensaje> mensajesRecibidos;


Entrada:

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

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int identrada;

    //bi-directional many-to-one association to Evento
    @ManyToOne
    @JoinColumn(name="evento")
    private Evento eventoBean;

    //bi-directional many-to-one association to Usuario
    @ManyToOne
    @JoinColumn(name="usuario")
    @JsonIgnore
    private Usuario usuarioBean;


我还有Evento班:

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

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int idevento;

    private String categoria;

    private String descripcion;

    @Column(name="entradas_disponibles")
    private int entradasDisponibles;

    @Column(name="entradas_venta")
    private int entradasVenta;

    private int estado;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="fecha_hora")
    private Date fechaHora;

    private String imagen;

    private String localizacion;

    @Column(name="precio_entrada")
    private double precioEntrada;

    private String titulo;

    //bi-directional many-to-one association to CompraEntrada
    @OneToMany(mappedBy="eventoBean")
    private List<CompraEntrada> compraEntradas;

    //bi-directional many-to-one association to Entrada
    @OneToMany(mappedBy="eventoBean")
    private List<Entrada> entradas;

    //bi-directional many-to-one association to Usuario
    @ManyToOne
    @JoinColumn(name="creador")
    private Usuario usuario;


我正在使用Spring Data,但是有递归序列化问题。
当我“打印” Usuario类型的对象时,它应该序列化Usuario的所有信息。这里的重点是,Entrada(Usuario中的List)具有Usuario类型的属性。

我不想序列化Entrada的Usuario。我只是想序列化Usuario列表中的每个项目。

我试图在Entrada中的Usuario类型的属性中添加@JsonIgnore,但是我仍然遇到相同的问题。

日志显示:

2017-12-04 18:57:46.980[0;39m [31mERROR[0;39m [35m3389[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.a.c.c.C.[.[.[/].[dispatcherServlet]   [0;39m [2m:[0;39m Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) (through reference chain: es.softcorp.domains.Entrada["eventoBean"]->es.softcorp.domains.Evento["entradas"]->org.hibernate.collection.internal.PersistentBag[0]->es.softcorp.domains.Entrada["eventoBean"]->es.softcorp.domains.Evento["entradas"]->org.hibernate.collection.internal.PersistentBag[0]->es.softcorp.domains.Entrada["eventoBean"]->es.softcorp.domains.Evento["entradas"]-


等等

最佳答案

我已经解决了这个问题,根据我记得的@JsonIgnore的工作原理,必须禁用该类的自动字段检测功能,或者如果希望所有类都禁用此功能。

有两种方法可以解决递归问题。


Json批注将双向关系告知ObjectMapper。
@JsonIgnore@JsonView导致递归/循环的字段。


对于一个示例项目,我为所有此类禁用了自动字段检测功能,并在要序列化的类中使用了@JsonProperty@JsonIgnore。如果禁用了自动检测,则必须手动标记字段。

/**
 * Disable auto field detection for JSON message converter.
 * @return
 */
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();

    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    objectMapper.setVisibility(
            objectMapper
            .getVisibilityChecker()
            .with(Visibility.NONE)
    );

    jsonConverter.setObjectMapper(objectMapper);
    return jsonConverter;
}


还有一个@JsonView批注,其作用与@JsonIgnore相似,可用于选择要序列化的字段,这是进一步阅读https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring的链接

解决问题的正确方法是,如本页http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion所述,向ObjectMapper告知递归/双向关系。

总之,您在子级(非所有权方)上使用@JsonManagedReference,在父级(关系的所有权方)上使用@JsonBackReference

10-08 13:43