andreatomei98
andreatomei98

Reputation: 11

JSON failed to lazily initialize a collection of roles

I am doing an exercise on the CRUD operations in a many-to-many relationship having attributes in the relationship table.

I am attaching my entities and I hope you can help me.

The error mentioned above occurs when I go to ask for the list of elements on the zetautente and zetamessaggio tables.

The same error occurs even when I go to ask for a single element of one of the two above mentioned tables ..

@Entity(name = "ZetaMessaggio")
@Table(name="zetamessaggio")
public class ZetaMessaggio implements Serializable {

    private static final long serialVersionUID = -2387302703708194311L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "zetamessaggio_seq")
    @SequenceGenerator(name = "zetamessaggio_seq",sequenceName = "zetamessaggio_seq",allocationSize = 1)
    private Long id;

    @Column(name = "titolo")
    private String titolo;

    @Column(name = "testo")
    private String testo;

    @OneToMany(
            mappedBy = "zetaMessaggio",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    @JsonManagedReference(value="zetaMessaggio")
    private List<ZetaMessaggioUtente> zetaUtente = new ArrayList<ZetaMessaggioUtente>();


    public ZetaMessaggio() {
    }

    public ZetaMessaggio(String titolo, String testo)
    {
        this.titolo = titolo;
        this.testo = testo;
    }


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitolo() {
        return titolo;
    }

    public void setTitolo(String titolo) {
        this.titolo = titolo;
    }

    public String getTesto() {
        return testo;
    }

    public void setTesto(String testo) {
        this.testo = testo;
    }

    public List<ZetaMessaggioUtente> getZetaUtente() {
        return zetaUtente;
    }

    public void setZetaUtente(List<ZetaMessaggioUtente> zetaUtenti) {
        this.zetaUtente = zetaUtenti;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass())
            return false;

        ZetaMessaggio other = (ZetaMessaggio) o;
        return  Objects.equals(new Long(this.id), new Long(other.id))
                && Objects.equals(this.titolo, other.titolo)
                && Objects.equals(this.testo, other.testo);
    }

    @Override
    public int hashCode() {
        return Objects.hash(    new Long(this.id)
                , this.testo
                , this.titolo
        );
    }
}


@Entity(name = "ZetaMessaggioUtente")
@Table(name = "zetamessaggioutente")
public class ZetaMessaggioUtente implements Serializable {

    private static final long serialVersionUID = 4060038267093084727L;

    @EmbeddedId
    private ZetaMessaggioUtenteId id;

    @Column(name="data")
    private String data;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("idMessaggio")
    @JoinColumn(name = "idMessaggio")
    @JsonBackReference(value = "zetaMessaggio")
    private ZetaMessaggio zetaMessaggio;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("idUtente")
    @JoinColumn(name = "idUtente")
    @JsonBackReference(value = "zetaUtente")
    private ZetaUtente zetaUtente;

    private ZetaMessaggioUtente() {}

    public ZetaMessaggioUtente(ZetaMessaggioUtenteId id)
    {
        this.id = id;
    }

    public ZetaMessaggioUtente(ZetaMessaggio messaggio, ZetaUtente utente)
    {
        this.zetaMessaggio = messaggio;
        this.zetaUtente = utente;
        this.id = new ZetaMessaggioUtenteId(messaggio.getId(), utente.getId());
    }

    public ZetaMessaggioUtenteId getId() {
        return id;
    }

    public void setId(ZetaMessaggioUtenteId id) {
        this.id = id;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public ZetaMessaggio getZetaMessaggio() {
        return zetaMessaggio;
    }

    public void setZetaMessaggio(ZetaMessaggio zetaMessaggio) {
        this.zetaMessaggio = zetaMessaggio;
    }

    public ZetaUtente getZetaUtente() {
        return zetaUtente;
    }

    public void setZetaUtente(ZetaUtente zetaUtente) {
        this.zetaUtente = zetaUtente;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass())
        {
            return false;
        }

        ZetaMessaggioUtente other = (ZetaMessaggioUtente) o;
        return  Objects.equals(zetaMessaggio, other.zetaMessaggio)
                && Objects.equals(zetaUtente, other.zetaUtente)
                ;
    }

    @Override
    public int hashCode()
    {
        return Objects.hash(zetaMessaggio, zetaUtente);
    }
}


@Embeddable
public class ZetaMessaggioUtenteId implements Serializable {

    private static final long serialVersionUID = -7372159721389421199L;

    @Column(name = "idMessaggio")
    private Long idMessaggio;

    @Column(name = "idUtente")
    private Long idUtente;

    private ZetaMessaggioUtenteId(){}

    public ZetaMessaggioUtenteId(Long idMessaggio,Long idUtente){
        setIdMessaggio(idMessaggio);
        setIdUtente(idUtente);
    }

    public Long getIdMessaggio() {
        return idMessaggio;
    }

    public void setIdMessaggio(Long idMessaggio) {
        this.idMessaggio = idMessaggio;
    }

    public Long getIdUtente() {
        return idUtente;
    }

    public void setIdUtente(Long idUtente) {
        this.idUtente = idUtente;
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass())
        {
            return false;
        }

        ZetaMessaggioUtenteId other = (ZetaMessaggioUtenteId) o;
        return Objects.equals(new Long(this.idMessaggio), new Long(other.idMessaggio)) &&
                Objects.equals(new Long(this.idUtente), new Long(other.idUtente))
                ;
    }

    @Override
    public int hashCode()
    {
        return Objects.hash(    new Long(this.idMessaggio)
                , new Long(this.idUtente)
        );
    }
}


@Entity(name = "ZetaUtenti")
@Table(name = "zetautenti",uniqueConstraints = {@UniqueConstraint(columnNames = {"Id"})})
public class ZetaUtente implements Serializable {

    private static final long serialVersionUID = -5338956772143977741L;

    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "zetautenti_seq")
    @SequenceGenerator(name = "zetautenti_seq",sequenceName = "zetautenti_seq",allocationSize = 1)
    private Long id;

    @Column(name = "nome")
    private String nome;

    @Column(name = "cognome")
    private String cognome;

    @OneToMany(
            mappedBy = "zetaUtente",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    @JsonManagedReference(value="zetaUtente")
    private List<ZetaMessaggioUtente> zetaMessaggio = new ArrayList<ZetaMessaggioUtente>();


    public ZetaUtente() {
    }

    public ZetaUtente(String nome, String cognome)
    {
        this.nome = nome;
        this.cognome = cognome;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getCognome() {
        return cognome;
    }

    public void setCognome(String cognome) {
        this.cognome = cognome;
    }

    public List<ZetaMessaggioUtente> getZetaMessaggio() {
        return zetaMessaggio;
    }

    public void setZetaMessaggio(List<ZetaMessaggioUtente> zetaMessaggi) {
        this.zetaMessaggio = zetaMessaggi;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass())
            return false;

        ZetaUtente other = (ZetaUtente) o;
        return  Objects.equals(new Long(this.id), new Long(other.id))
                && Objects.equals(this.nome, other.nome)
                && Objects.equals(this.cognome, other.cognome);
    }

    @Override
    public int hashCode() {
        return Objects.hash(    new Long(this.id)
                , this.nome
                , this.cognome
        );
    }
}

Upvotes: 1

Views: 108

Answers (2)

Dmitry Ionash
Dmitry Ionash

Reputation: 821

By default @OneToMany and @ManyToMany relationships are lazy, so you need to handle receiving lazy data.

There are plenty of advices on the internet, it's very strange that you are asking this question, but if very quickly, you have few ways for getting lazy collection:

  • Antipatterns: OpenSessionInView and enable_lazy_load_no_trans

  • Most popular way: to use @Transactional annotation (auto attach object to session pool) or manual with start transaction, get collection, close transactional

  • Similar way: Hibernate.initialize(<get collection method>)

  • Manual way: use own SQL request with "JOIN FETCH ..."

  • Alternative way: to use @Fetch(FetchMode.SUBSELECT) (cannot say anything)

  • Not proper way (but the fastest temporary solution): to use FetchMode.EAGER for collection

Upvotes: 1

Joker
Joker

Reputation: 11146

Collections are lazily loaded by default, if you are not aware of this thing then you can check the link Lazy loading of collection.

To make your code working you need to add following in OneToMany :

fetch = FetchType.EAGER

Upvotes: 0

Related Questions