A LazyCollectionOption.EXTRA megismerése
De a legérdekesebb a LazyCollectionOption.EXTRA érték. Ha ezt a @LazyCollection annotáció értékeként adja meg , akkor a Hibernate a lehető legtovább késlelteti a gyűjtemény elemeinek betöltését.
Ha megpróbálja lekérni a gyűjtemény elemeinek számát:
User user = session.load(User.class, 1);
List<Comment> comments = user.getComments();
int count = commetns.size();
Ekkor a Hibernate az összes kódra csak egy lekérdezést hajt végre:
SELECT COUNT(id) FROM comment WHERE user_id = 1;
Ha azonban egy megjegyzést szeretne kapni a gyűjteményből, például a 3. számot:
User user = session.load(User.class, 1);
List<Comment> comments = user.getComments();
Comment comment = commetns.get(3);
Ekkor felmerül a kérdés: honnan kellene tudnia a Hibernate-nak, hogy az elem a harmadik anélkül, hogy az összes elemet a memóriába töltené?
A probléma megoldására javasolt egy további oszlop létrehozása a megjegyzéstáblázatban, amely a megjegyzés sorszámát tárolja a megjegyzésgyűjteményben. És ehhez is szükség van egy speciális megjegyzésre - @OrderColumn .
Így nézne ki a megoldás:
@Entity
@Table(name=”user”)
class User {
@Column(name=”id”)
public Integer id;
@OneToMany(cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.EXTRA)
@OrderColumn(name = "order_id")
public List<Comment> comments;
}
A LazyCollectionOption.EXTRA fő előnye
A LazyCollectionOption.EXTRA legerősebb előnyét akkor látjuk, ha a @ManyToMany annotációval adjuk meg . Vegyük a régi esetünket, ahol van egy alkalmazottunk, egy feladatunk, és egy felhasználóhoz sok feladatot rendelhetünk.
Java osztályaink így néznek ki:
Alkalmazotti osztály :
@Entity
@Table(name=”employee”)
class Employee {
@Column(name=”id”)
public Integer id;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="employee_task",
joinColumns= @JoinColumn(name="employee_id", referencedColumnName="id"),
inverseJoinColumns= @JoinColumn(name="task_id", referencedColumnName="id") )
@LazyCollection(LazyCollectionOption.EXTRA)
private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();
}
És az EmployeeTask osztály :
@Entity
@Table(name=”task”)
class EmployeeTask {
@Column(name=”id”)
public Integer id;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="employee_task",
joinColumns= @JoinColumn(name="task_id", referencedColumnName="id"),
inverseJoinColumns= @JoinColumn(name=" employee_id", referencedColumnName="id") )
@LazyCollection(LazyCollectionOption.EXTRA)
private Set<Employee> employees = new HashSet<Employee>();
}
És ahhoz, hogy feladatot adjon a rendezőhöz, valami ehhez hasonló kódot kell írnia:
Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employees.add(director);
session.update(task);
session.flush();
Tehát, ha a Task osztályban az alkalmazottak mezője rendelkezik a LazyCollectionOption.EXTRA megjegyzéssel, akkor az alkalmazottak gyűjteménye (a Task osztályban) és a feladatgyűjtemény (az Employee osztályban) soha nem töltődik be az adatbázisból .
Amikor ez a kód lefut, csak egy rekord kerül beillesztésre a munkavállalói_feladat szolgáltatási táblába, amely, mint emlékszel, valahogy így néz ki:
munkavállaló_feladat táblázat :munkavállalói azonosító | feladat_azonosítója |
---|---|
1 | 1 |
2 | 2 |
5 | 3 |
5 | 4 |
5 | 5 |
4 | 7 |
6 | 8 |
4 | 101 |
A hozzáadott sor zöld színnel van kiemelve. Ennek a sornak a hozzáadásához nem kell gyűjteményeket betöltenie az adatbázisból - a Hibernate megteszi ezt nélküle. Pontosan ez az eset, amikor a LazyCollectionOption.EXTRA nagymértékben felgyorsítja az adatbázissal végzett munkát.
N+1 probléma
De persze ennek a módnak van egy árnyoldala is. Például a LazyCollectionOption.EXTRA annotáció N+1 problémát generál .
Ha úgy dönt, hogy végignézi felhasználói megjegyzéseit:
User user = session.load(User.class, 1);
List<Comment> comments = user.getComments();
for (Comment comment : comments) {
System.out.println(comment);
}
Ezután a hibernálás külön kérésre fog végrehajtani minden egyes megjegyzés objektumhoz. És még egy további lekérdezés az összes megjegyzés számának megtekintéséhez. Ez jelentősen lelassíthatja a kódot.
Ha a felhasználónak 1000 megjegyzése van, akkor a Hibernate 1001 lekérdezést hajt végre az adatbázisban, hogy végrehajtsa ezt a kódot, bár eggyel is megteheti. Ha előre tudtad, hogy szükséged lesz ennek az osztálynak az összes objektumára.
GO TO FULL VERSION