MultipleBagFetchException z encja dziedziczona

0

Cześć - mam pewien problem otoz:

mam klase:

@Getter
@Setter
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "GenericClass")
public class GenericClass {
......
}

dzieki ktorej dziedzicze do drugiej klasy i mam w niej 3 odniesienia hibernetawe @OneToMany - bidirectional:

@Getter
@Setter
@Entity(name = "NonGeneric")
@DiscriminatorValue("NonGeneric")
public class NonGeneric extends GenericClass {

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "cosTam", cascade = CascadeType.ALL)
    private List<TagA> tagsA;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "cosTam", cascade = CascadeType.ALL)
    private List<TagB> tagsB;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "cosTam", cascade = CascadeType.ALL)
    private List<TagC> tagsC;

}

wywołuję z repozytorium Jpa (interfejsu ktora ma JpaSpecificationExecutor) takie cos:

    public Specification<NonGeneric> getAllNonGenerics() {
        return (root, query, cb) -> {
            if (query.getResultType().equals(NonGeneric.class)) {
                root.fetch("tagsA", JoinType.LEFT);
                root.fetch("tagsB", JoinType.LEFT);
                root.fetch("tagsC", JoinType.LEFT);
            }
            Specification<NonGeneric> spec = where(null);

            assert spec != null;
            return spec.toPredicate(root, query, cb);
        };
    }

Specyfikacja dziala dla innych rzeczy a tutaj nie..
i dostaję:
org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags - dalej wymienione tagsA tagsB tagsC etc..

Jakie macie rozwiazania na to? Moze zmienic troche relacje? potrzebuje na raz sciagnac calosc..

0

@Charles_Ray: Niestety nie dziala ze specyfikacjami.. zrobilem 3 metody ktora kazda 'fetchuje' co innego ale to nie ma sensu chyba ze specyfikacjami.. szukam cos zeby dalo rade to obsluzyc

0

Ok działa - trzeba było w sesji hibernetowej włożyć te queriesy @Transactional pomogl;) dzieki ale mam jeszcze jedno pytanie:

Otóż co jest lepsze dla tego typu modelu gdzie przewiduje maksymalnie w tych TagsA tagsB tagsC od 1 do 10 elementów?
Nie lepiej ustawić seta w nich a potem uzywajac specification repo stworzyc jedno wielkie query z 3 leftjoinami i jakas logika czy wlasnie dzielic na 3 rozne query?

Jak to by wygladala wzgledem performance i ogólnie waszym zdaniem?

2

Użyj Set a nie List i problem zniknie...

Swoją drogą

@Getter
@Setter
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "GenericClass")

I jeszcze @Transactional. Jak masz więcej adnotacji niż kodu to ja zacząłbym sie zastanawiać na życiowymi wyborami.

ogólnie waszym zdaniem

Ogólnie to nie użyłbym JPA. Bo teraz to klasycznie walczysz z technologią, zamiast napisać proste query za pomocą jakiegoś jOOQ albo QueryDSLa albo i gołego sqla przez JDBI/Spring JDBC Template.

To jest taki klasyczny rabbit hole z JPA/Hibernate -> upisałeś się tych wszystkich klas Entity, które i tak zaraz po wyjęciu z bazy przemapowujesz pewnie na jakieś obiekty domenowe zeby móc z tym pracować. Do tego robisz jakieś potężne fikołki żeby w ogóle wybrać z bazy to co cię interesuje. Gdzie tu dokładnie jest zysk?

0

@Shalom: Nie widze nic zlego w lomboku | Entity/Inheritance/DiscriminatorColumn - racja, przesada

A i z tego co czytam to z List na Set zamienie problem znika ale performance problem juz nie, bo mi powstaje cartesian product X * Y * Z * ...

Transactional byl potrzebny do przykladu kolegi z góry;) ale nie tą drogą raczej chce iść.

Również schodzę do tego samego wniosku że lepiej napisać query lub skorzystać z Dsla/CriteriaBuildera(choć to chyba leci przez hibernate) czy JooQ dlatego pytam zanim zrobie jakis pseudo-benchmark na swojej bazie, czy lepsze byłoby używanie contextu hibernetowego czy jednak 1 większe query ;) majac na wzglad performance

1 użytkowników online, w tym zalogowanych: 0, gości: 1