Come ottimizzare un'entità gonfiata che causa una query enorme

2

Ho un'applicazione che espone una serie di servizi Web. Una delle mie entità ha un mucchio di relazioni uno-a-molti e molti-a-molti con altre entità. Il mio livello di transnazionalità è in DAO e mi piacerebbe tenerlo lì per evitare che il contesto di persistenza venga aperto troppo a lungo. Pensare di spostarlo fino al livello di servizio o specialmente lasciandolo aperto per la richiesta completa mi dà i timori. Quindi ho dovuto contrassegnare tutte le associazioni come ansiose.

Il risultato è ovviamente che quando lo si recupera, Hibernate genera una query massiccia che sta iniziando a rallentare. Sono andato con 'l'ottimizzazione prematura è la radice di tutti i mali', ma è qualcosa che deve essere già affrontato.

Il mio problema è che, dato che voglio mantenere @Transactional a livello di DAO, ho due opzioni (abbastanza simili):

  1. Impostare le associazioni come pigre e interrogare manualmente DB e impostarle prima di ottenere una proprietà corrispondente. Quindi, dove ho

    // entity
    @OneToMany(fetch = EAGER, mappedBy = "user", cascade = {ALL}, orphanRemoval = true)
    private final Set<Order> orders = new HashSet<>();
    
    // usage
    user.getOrders()
    

Mi piacerebbe cambiare:

    // entity
    @OneToMany(fetch = LAZY, mappedBy = "user", cascade = {ALL}, orphanRemoval = true)
    private final Set<Order> orders = new HashSet<>();

    // usage
    Set<Order> orders = orderDao.findByUserId(user.getId());
    user.setOrders(orders);
    user.getOrders()

Questo non mi sembra giusto, perché capisco che lo scopo di avere una relazione Hibernate è lasciare che Hibernate lo gestisca. D'altra parte, avrei comunque il vantaggio di avere Hibernate nella gestione degli aggiornamenti e degli inserti.

  1. Rimuovi completamente la relazione al livello di Hibernate e gestiscili completamente manualmente. Certo, questo non è estremamente, ma piuttosto doloroso.

C'è qualche altra opzione? Qual è il solito percorso di ottimizzazione in casi come questo?

    
posta garci560 11.04.2016 - 18:11
fonte

1 risposta

2

Soluzioni comuni a questa classe di problemi:

  1. Usa HQL. Nei metodi DAO che sono per scopi specifici, è facile usare un HQL personalizzato con (left) join fetch per specificare esattamente quali dati si desidera pre-compilare nel modello.

  2. Riferimento manuale alle raccolte caricate pigramente. Per esempio. chiama manualmente user.getOrders().size() in alcuni metodi DAO. Questo ha lo stesso effetto del # 1 ma non richiede la query HQL.

  3. Annota in modo selettivo i metodi di servizio con @Transactional . Dovresti sapere esattamente quali dati sono necessari per il livello vista. L'estensione selettiva delle transazioni fino al livello di servizio dovrebbe coprire gli altri casi.

risposta data 11.04.2016 - 20:00
fonte

Leggi altre domande sui tag