1.1 A probléma háttere
Amikor valódi adatbázisokkal kezd dolgozni, azonnal eszébe jut a „korai optimalizálás minden rossz gyökere” kifejezés. Csak most negatívan emlékszel rá. Ha adatbázissal dolgozik, az optimalizálás elengedhetetlen. És már a tervezési szakaszban dolgozni kell vele.
A hibernálás nagyon kényelmessé teszi az adatbázissal való munkát. Könnyen megszerezhet bármilyen gyermekobjektumot, csak megfelelő megjegyzésekkel @OneToMany
és @ManyToMany
. Példa:
@Entity
@Table(name="user")
class User {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "user_id")
public List<Comment> comments;
}
És milyen egyszerű megszerezni a felhasználók megjegyzéseit:
User user = session.get(User.class, 1);
List<Comment> comments = user.getComments();
És nagy meglepetésben lesz részed. A felhasználónak több ezer megjegyzése van. Ha ilyen kódot ír, a Hibernate természetesen betölti a felhasználó összes megjegyzését. De nagyon lassú lesz, a megjegyzések sok memóriát foglalnak el és így tovább.
Ezért nem lehet így írni! Elméletben igen, de a gyakorlatban nem.
1.2 Tovább rontja a dolgokat gyűjteményekkel
A probléma még érdekesebb. Végül is, általában soha nem kell a felhasználó összes megjegyzése. Még ha megjeleníted is őket valahol a kliensen, inkább részenként - oldalakon - csinálod.
Tehát ilyen módszerekre van szükség:
public class CommentsManager {
private static final PAGE_SIZE = 50;
public List<Comment> getCommentsPage(int userId, int pageIndex){
User user = session.get(User.class, userId);
List<Comment> comments = user.getComments();
return comments.subList(pageIndex * PAGE_SIZE, PAGE_SIZE);
}
public int getCommentsPageCount(int userId) {
User user = session.get(User.class, userId);
List<Comment> comments = user.getComments();
return Math.ceil( comments.size()/PAGE_SIZE);
}
}
Az első módszer csak egy oldalnyi megjegyzést ad vissza - 50 darabot. A második módszer a megjegyzések oldalainak számát adja vissza. És ez a legrosszabb. Ahhoz, hogy egyszerűen megtudja a hozzászólások számát, le kellett töltenie az összes megjegyzést az adatbázisból!
1.3 Fény az alagút végén
Ezért senki sem használja csodálatos gyermekgyűjteményeinket. Nem, természetesen használják, de csak a HQL lekérdezések részeként. Például így:
public class CommentsManager {
private static final PAGE_SIZE = 50;
public List<Comment> getCommentsPage(int userId, int pageIndex){
String hql = "select comments from User where id = :id";
Query<Comment> query = session.createQuery( hql, Comment.class);
query.setParametr("id", userId);
query.setOffset(pageIndex * PAGE_SIZE);
query.setLimit(PAGE_SIZE);
return query.list();
}
public int getCommentsPageCount(int userId) {
String hql = "select count(comments) from User where id = :id";
Query<Integer> query = session.createQuery( hql, Integer.class);
query.setParametr("id", userId);
return Math.ceil(query.singleResult()/PAGE_SIZE);
}
}
Jó hír, hogy módszereinket úgy tudjuk megvalósítani, hogy ne kelljen extra adatokat betöltenünk az adatbázisból. A rossz hír az, hogy nem könnyű dolgozni gyűjteményeinkkel.
GO TO FULL VERSION