Spring Data: Wie kann ich das Datenmodell richtig definieren?

lam_tr

Top Contributor
Hallo zusammen,

ich habe hier ein Spring Boot Anwendung zur Ticketverwaltung am Laufen. Bisher ging es ganz gut bis ich eine Liste von Attachment ergänzt habe. Jetzt bekomme ich folgende Fehlermeldung.

Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [Ticket.referencedTickets, Ticket.attachments]

Java:
@Entity
public class Ticket extends BaseEntity {

    @OneToOne
    private User owner;

    @OneToOne
    private User author;

    @ManyToOne
    @JoinColumn(name = "project_id", nullable = false)
    private Project project;

    @Lob
    private String description;
    private String component;
    private String type;
    private String result;
    private String resultVariant;
    private int definitionOfDone;
    private TicketStatus status;
    private TicketPriority priority;

    @ManyToMany(fetch = FetchType.EAGER)
    private List<Ticket> referencedTickets = new ArrayList<>();

    @OneToMany(mappedBy = "ticket", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<Attachment> attachments = new ArrayList<>();
    
    ...
}

Was mache ich an der Stelle falsch?

Viele grüße
lam
 
Das FetchType.EAGER an beiden Listen.
Die Fehlermeldung sagt, dass das nicht geht. Hibernate muss effektiv hier mehrere SQL-Queries absetzen, du verbietest es ihm aber dadurch, dass du beide Listen als earger fetched markierst.
und wenn ich bei attachments anstatt EAGER auf LAZY mache, wann wird diese Querie ausgeführt.

Ich benötige sozusagen, sobald das Object Ticket geladen wird, sollen references und attachments vorhanden sein.
 
Das erste Mal, wenn du auf Elemente der Liste zugreifen möchtest (per Index oder über Iteration).
Jetzt habe ich das Datenmodell so angepasst

Java:
    @ManyToMany(fetch = FetchType.LAZY)
    private List<Ticket> referencedTickets;

    @OneToMany(mappedBy = "ticket", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Attachment> attachments;

Wenn ich referencedTickets hole, bekomme ich folgende Meldung

Java:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role Ticket.referencedTickets, could not initialize proxy - no Session

Beim Holen des ersten Tickets von der Liste, erscheint die Fehlermeldung.
Java:
ticket.getReferencedTickets().get(0);
ticket.getReferencedTickets();

So würde es ach nicht gehen oder?
 
Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [Ticket.referencedTickets, Ticket.attachments]
Du nutzt Listen, und keine Sets. Ersetz die List einfach durch Set, dann sollte das auch mit EAGER klappen.

Wenn ich referencedTickets hole, bekomme ich folgende Meldung

Java:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role Ticket.referencedTickets, could not initialize proxy - no Session
Du befindest dich beim Benutzen der Liste auserhalb einer Transaktion, je nachdem was du machst solltest du entweder Transaktions-Grenzen passend setzen oder das auf einfache "DTOs" mappen oder das Laden innerhalb einer Transaktion erzwingen, indem du die Liste benutzt (in absteigender Präferenz, wobei es ein bisschen auf den Kontext ankommt)
 
FetchType.EAGER löst zwar vermeintlich viele Probleme, ist aber oftmals eine schlechte Idee. Beim Entwickeln mag das noch nicht auffallen, wenn die Datenbank aus 10 Zeilen Testdaten besteht. In der produktiven Applikation treten dann aber oft Performance Probleme auf.

 

Zurück
Oben