How to optimize the selection of multiple collections in Hibernate?

I am trying to improve application performance using Hibernate, which performs too many SQL calls in a database. I think data sampling can be grouped together to reduce the number of calls and improve performance, but I'm losing a bit here. I looked at the Hibernate documentation on subqueries and batch fetching that helps, but I don't think it completely fixes the problem.

In the example below, I need to get detailed information about the list of soldiers that make up the troops and display them on a web page.

@Entity
public class Troop {
    @OneToMany(mappedBy="troop")
    public List<Soldier> getSoldiers() {
   ...
}

It is easy to set a sampling strategy for a subquery that is batch or desired to retrieve all the soldiers of this unit without too many SQL statements.

@Entity
public class Soldier {
    @Id
    String soldierId

    String firstName;
    String lastName;

    @OneToMany(mappedBy="address")
    public List<Soldier> getAddress() {
     ...
    @OneToMany(mappedBy="combatHistory")
    public List<Soldier> getCombatHistory() {
      ...
    @OneToMany(mappedBy="medicalHistory")
    public List<Soldier> getMedicalHistory() {
      ...
}

, . . 3 , 1000 , 3- SQL!

, ? soldierIds, , ?

,

from Address as a where a.soldierId in (...)
from CombatHistory as a where a.soldierId in (...)
from MedicalHistory as a where a.soldierId in (...)

Address, CombatHistory .. , SQL . ( 3), (3 1000).

, . , , , Hibernate .

HibernateException: cannot simultaneously fetch multiple bags 
+5
2

@Fetch (FetchMode.SUBSELECT) "" , SQL.

@Entity
public class Country implements java.io.Serializable {

    private long id;
    private int version;
    private String country;
    private Set<City> cities = new HashSet<City>(0);

    @Fetch(FetchMode.SUBSELECT)
    @OneToMany(mappedBy = "country", cascade = CascadeType.ALL)
    public Set<City> getCities() {
        return cities;
    }


    ...
}

, :

    public List<Country> selectCountrySubSelect() {
        List<Country> list = getSession().createQuery("select c from Country c").list();
        // You don't have to initialize every collections
        // for (Country country : list) {
        // Hibernate.initialize(country.getCities());
        // }
        // but just "touch" one, and all will be initialized
        Hibernate.initialize(((Country) list.get(0)).getCities());
        return list;
    }

:

DEBUG org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections():  - 2 collections were found in result set for role: business.hb.Country.cities
DEBUG org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection():  - Collection fully initialized: [business.hb.Country.cities#1]
DEBUG org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection():  - Collection fully initialized: [business.hb.Country.cities#2]
DEBUG org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections():  - 2 collections initialized for role: business.hb.Country.cities
DEBUG org.hibernate.engine.internal.StatefulPersistenceContext.initializeNonLazyCollections():  - Initializing non-lazy collections
+3

hibernate, , . , .

from Soldier s left join fetch s.Address where s.soldierId in (...)
from Soldier s left join fetch s.CombatHistory where s.soldierId in (...)
from Soldier s left join fetch s.MedicalHistory where s.soldierId in (...)

3.

0

All Articles