1. Introduktion
I den här korta guiden tar vi en titt på olika FetchMode- värden som vi kan använda i @ org.hibernate.annotations.Fetch annotation.
2. Ställa in exemplet
Som ett exempel använder vi följande kundenhet med bara två egenskaper - ett id och en uppsättning beställningar:
@Entity public class Customer { @Id @GeneratedValue private Long id; @OneToMany(mappedBy = "customer") @Fetch(value = FetchMode.SELECT) private Set orders = new HashSet(); // getters and setters }
Vi skapar också en beställningsenhet bestående av ett id, ett namn och en hänvisning till kunden .
@Entity public class Order { @Id @GeneratedValue private Long id; private String name; @ManyToOne @JoinColumn(name = "customer_id") private Customer customer; // getters and setters }
I vart och ett av nästa avsnitt hämtar vi kunden från databasen och får alla beställningar:
Customer customer = customerRepository.findById(id).get(); Set orders = customer.getOrders();
3. FetchMode.SELECT
På vår kundenhet har vi kommenterat beställningsegenskapen med en @Fetch- kommentar:
@OneToMany @Fetch(FetchMode.SELECT) private Set orders;
Vi använder @Fetch för att beskriva hur Hibernate ska hämta fastigheten när vi letar upp en kund.
Att använda SELECT indikerar att egenskapen ska laddas lat.
Detta betyder att för första raden:
Customer customer = customerRepository.findById(id).get();
Vi ser inte en koppling med ordertabellen:
Hibernate: select ...from customer where customer0_.id=?
Och det för nästa rad:
Customer customer = customerRepository.findById(id).get();
Vi kommer att se efterföljande frågor för relaterade beställningar:
Hibernate: select ...from order where order0_.customer_id=?
Den Hibernate FetchMode.SELECT genererar en separat fråga för varje Order som behöver laddas.
I vårt exempel ger det en fråga för att ladda kunderna och ytterligare fem frågor för att ladda ordersamlingen.
Detta kallas n + 1-valproblemet. Exekvera en fråga kommer att utlösa n ytterligare frågor.
3.1. @ BatchSize
FetchMode.SELECT har en valfri konfigurationsanteckning med @BatchSize- anteckningen:
@OneToMany @Fetch(FetchMode.SELECT) @BatchSize(size=10) private Set orders;
Hibernate kommer att försöka ladda ordersamlingen i partier som definieras av storleksparametern .
I vårt exempel har vi bara fem order så en fråga räcker.
Vi använder fortfarande samma fråga:
Hibernate: select ...from order where order0_.customer_id=?
Men det kommer bara att köras en gång. Nu har vi bara två frågor: En för att ladda kunden och en för att ladda ordersamlingen.
4. FetchMode.JOIN
Medan FetchMode.SELECT laddar relationer lat, FetchMode.JOIN laddar dem ivrigt, säg via en join:
@OneToMany @Fetch(FetchMode.JOIN) private Set orders;
Detta resulterar i bara en fråga för både kunden och deras order :
Hibernate: select ... from customer customer0_ left outer join order order1 on customer.id=order.customer_id where customer.id=?
5. FetchMode.SUBSELECT
Eftersom beställningsegenskapen är en samling kan vi också använda FetchMode.SUBSELECT :
@OneToMany @Fetch(FetchMode.SUBSELECT) private Set orders;
Vi kan bara använda SUBSELECT med samlingar.
Med den här inställningen går vi tillbaka till en fråga för kunden:
Hibernate: select ... from customer customer0_
Och en fråga för ordern , med hjälp av en underval denna gång:
Hibernate: select ... from order order0_ where order0_.customer_id in ( select customer0_.id from customer customer0_ )
6. FetchMode vs. FetchType
I allmänhet definierar FetchMode hur Hibernate ska hämta data (genom att välja, gå med eller välja under). FetchType definierar å andra sidan om Hibernate kommer att ladda data ivrigt eller lat.
De exakta reglerna mellan dessa två är följande:
- om koden inte ställer in FetchMode är standard JOIN och FetchType fungerar som definierat
- med FetchMode.SELECT eller FetchMode.SUBSELECT- uppsättning fungerar FetchType också som definierat
- med FetchMode.JOIN- uppsättningen ignoreras FetchType och en fråga är alltid ivrig
För mer information hänvisas till Eager / Lazy Loading in Hibernate.
7. Slutsats
I denna handledning har vi lärt oss om FetchModes olika värden och hur de är relaterade till FetchType .
Som alltid finns all källkod tillgänglig på GitHub.