FetchMode i viloläge

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.