Multiples @ElementCollection in two different classes @Embeddable

1

I have an entity with two Embedded classes of the same type, and each has an ElementCollection of the same type, too. The business logic seems to be correct, but I'm experiencing some problems with the lack of knowledge in JPA.

Here are my classes:

@Entity
public class Etapa extends EntidadeBase {

    @Embedded
    private CronogramaDeDesembolso cronogramaDeReceita;

    @Embedded
    private CronogramaDeDesembolso cronogramaDeDespesa;
}

@Embeddable
public class CronogramaDeDesembolso {

    @ElementCollection
    private List<Parcela> parcelas;
}

I'm getting the following error log:

  

Caused by: org.hibernate.HibernateException: Found shared references to a collection: nexxus.convenioestadual.dominio.planodetrabalho.etapa.Etapa.Renote.recovery.parcelas

Does anyone have any idea what might be wrong and how to fix it?

    
asked by anonymous 18.08.2016 / 19:09

1 answer

1

Hibernate will experience this problem when it tries to persist more than one entity it manages that share the same instance of a collection.

For example, this scenario will exhibit this problem:

final Parcela parcela01 = ...
final Parcela parcela02 = ...

final List<Parcela> parcelas = Stream.of(parcela01, parcela02).collect(Collectors.toList());

final CronogramaDeDesembolso despesa = ...
despesa.setParcelas(parcelas);

final CronogramaDeDesembolso receita = ...
receita.setParcelas(parcelas);

final Etapa etapa = ...
etapa.setCronogramaDeDespesa(despesa);
etapa.setCronogramaDeReceita(receita);

// fazer o que mais for necessário e atualizar a instância (persist/merge/etc.)
em.persist(etapa);

It is important to note that what should not be the same is the collection, the items in the collection can be the same. The solution in this case is to just have another collection, something like this:

final Parcela parcela01 = ...
final Parcela parcela02 = ...

final List<Parcela> parcelasDespesa = Stream.of(parcela01, parcela02).collect(Collectors.toList());
final List<Parcela> parcelasReceita = Stream.of(parcela01, parcela02).collect(Collectors.toList());

final CronogramaDeDesembolso despesa = ...
despesa.setParcelas(parcelasDespesa);

final CronogramaDeDesembolso receita = ...
receita.setParcelas(parcelasReceita);

final Etapa etapa = ...
etapa.setCronogramaDeDespesa(despesa);
etapa.setCronogramaDeReceita(receita);

Notice that different objects are generated by collecting stream . Just having two different collections, but receiving from the previous one, will also bring on the problem, something like this:

final List<Parcela> parcelasDespesa = Stream.of(parcela01, parcela02).collect(Collectors.toList());
final List<Parcela> parcelasReceita = parcelasDespesa;

There are other scenarios that also occur, even if less common, as in applications that process competing for the same collection. In all scenarios, however, the cause is the same, the same instance of the collection present in different instances managed by provider .

The central point is: do not compare collections between different objects that are or will be managed by hibernate:)

    
19.08.2016 / 21:06