Relacionamento @OneToOne bidirecional

Pessoal to com uma duvida bem sinistra, bom fiz um relacionamento OneToOne entre a Classe Cliente e DetalhesDoCliente, bom a ideia é que o relacionamento seja Bidirecional e as duas classes tenham referencia uma a outra,

DetalhesDoCliente:

	@OneToOne
	@JoinColumn(name = "cliente", nullable = false)
	private Cliente cliente;

Cliente:

 	@OneToOne(mappedBy = "cliente")
	@JoinColumn(name = "registro", nullable = false)
	private DetalhesDoCliente registro;

Mas na hora que busco uma destas classes, entra em um loop, eu entendi oque acontece, por exemplo, Quando carrego Cliente, ele vem até DetalhesDoCliente.cliente, e assim inicia de novo o loop e continua, bom andei pesquisando mas não sei como resolver, poderiam me ajudar? desde já agradeço;

Remove esse @JoinColumn(name = "registro", nullable = false)

Não, não adiantou, realmente bidirecional eu não consigo fazer sem dar este loop…

Como assim loop?

Algo relacionado a isso?

DetalhesDoCliente.clitente.detalhesdocliente.cliente

É isso?

Isso, e fica nisso.

O erro que tenho quando tento buscar é este.

at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156)
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:575)
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:663)

Bom, a forma mais simples de resolver esse problema é utilizar um DTO para remover a dependência cíclica.

E isso vai acontecer independente de ser @OneToOne.

Utilizar entidades como objeto de tela serializados via JSON terá sempre esses problemas.

1 curtida

Usa Dto amigo, é a forma mais simples, segue um link com exemplo de classe Dto

1 curtida

Obrigado pessoal,

Uma outra forma de resolver sem colocar DTO’s no meio é usar as anotações @JsonManagedReference e @JsonBackReference. Elas servem exatamente para este tipo de problema e funcionam da seguinte forma:

  • JsonManagedReference é a referencia gerenciada do objeto, ou seja, vai seguir o fluxo de serialização normalmente.

  • JsonBackReference desacopla o objeto do fluxo de serialização e cria-se uma referência do mesmo no momento da serialização.

Veja no seu próprio exemplo:

@OneToOne
@JoinColumn(name = "cliente", nullable = false)
@JsonManagedReference
private Cliente cliente;


@OneToOne(mappedBy = "cliente")
@JoinColumn(name = "registro", nullable = false) // se vc tem a coluna registro no seu modelo de cliente, não precisa do mappedBy. Se vc não tem essa coluna, mas o relacionamento é necessário, vc não precisa do JoinColumn
@JsonBackReference
private DetalhesDoCliente registro;

Logo, quando vc buscar a entidade DetalhesDoCliente, o atributo Cliente - marcado como uma referência gerenciada - entrará no fluxo de serialização normalmente, porém, o atributo DetalhesDoCliente já na classe Cliente, está anotado como uma referência de volta, logo, sua serialização será ignorada pelo Jersey. Isso resolve de forma mais amigável e correta o problema de recursividade infinita.

Imagine se vc tiver 100 classes com relacionamento semelhante. Terá que criar 100 DTO’s? Particularmente, não gosto desta solução.

Resumindo de forma grosseira:

  • JsonManagedReference indica que o atributo deve ser serializado
  • JsonBackReference cria uma dependência lógica do atributo, mas não o serializa.

Ah, os recursos são do pacote com.fasterxml.jackson.annotation

1 curtida

Realmente muito legal isto, mas no caso eu estou usando Jersey-Moxy para serealizar meus objetos em json, e ao usar estes recursos, infelizmente n aceita…

Veja se essa thread do StackOverflow te ajuda. A solução é semelhante a esta que te falei e usa MOXy.

HAHAHAA MUITO BOMMMM, nossa como isso facilita vlw mesmo cara.

//DETALHES DO CLIENTE
@OneToOne
@JoinColumn(nullable = false)
@XmlElement
@XmlInverseReference(mappedBy="registro")
private Cliente cliente;

//CLIENTE
@OneToOne(mappedBy = "cliente")
@XmlElement
@XmlInverseReference(mappedBy="cliente")
private DetalhesDoCliente registro;