Vaadin is for application, serverside application. It's very nature to think about vaadin + hibernate. Before implementing my solution, I first search for discussions on Internet about this topic.
(I) Vaadin Wiki - Using Hibernate with Vaadin
http://vaadin.com/wiki/-/wiki/Main/Using%20Hibernate%20with%20Vaadin?p_r_p_185834411_title=Using+Hibernate+with+Vaadin
What I have learnt from this article:
(1) Hibernate is good, and has been used in many projects built or supported by IT Mill.
(2) session-per-request pattern for Hibernate session handling recommended as "often a safe bet"
(3) session-per-application / session-per-transaction are options may be considered, but not discussed. All discussion below are session-per-request
(4) to ensure one session per http request - use Hibernates getCurrentSession() to retrieve thread local session instance. Also begin transaction if none is active. (see code)
/**
* Used to get current Hibernate session. Also ensures an open Hibernate
* transaction.
*/
public Session getSession() {
Session currentSession = HibernateUtil.getSessionFactory()
.getCurrentSession();
if(!currentSession.getTransaction().isActive()) {
currentSession.beginTransaction();
}
return currentSession;
}
(5) to ensure close / flush session after each http request (against Vaadin nature to hide http request on the face): flush and close session in TransactionListener.transactionEnd() (see code)
getContext().addTransactionListener(new TransactionListener() {
public void transactionEnd(Application application,
Object transactionData) {
// Transaction listener gets fired for all contexts
// (HttpSessions) toolkit applications, checking to be this one.
if (application == WorkoutLog.this) {
closeSession();
}
}
public void transactionStart(Application application,
Object transactionData) {
}
});
private void closeSession() {
Session sess = HibernateUtil.getSessionFactory()
.getCurrentSession();
if(sess.getTransaction().isActive()) {
sess.getTransaction().commit();
}
sess.flush();
sess.close();
}
(6) recommendation for listing objects - "build good containers"
(7) may look at the HbnContainer code for idea on how to build a good container
(8) creating object - the article suggests implemented Container persist it with db.
(9) Update - the article suggests i.) using appropriate Item and a Form component, OR ii.) Table.setEditable()
(10) When work with form - mostly will need to extend / modify default FieldFactory
(11) The article use Container-central solution. Controller don't work with hibernate directly. Container (HbnContainer) and Property (Hbn...Property) do session.merge() kinds of things at backend.
(12) Table.ColumnGenerator to create columns not in Container
What shall not follow in this article:
(1) read hibernate manual, [quote] "usually update() or saveOrUpdate() are used in the following scenario... merge() is very different"
II. Pojo binding strategy for hibernate
http://vaadin.com/forum/-/message_boards/message/39711
What I have learnt from this article:
(1) Rizzo adopted the method different than that discussed in Hibernate manual, i.e. neither EXTENDED SESSION, nor SESSION-PER-REQUEST. He only uses the IDs of those persistent objects kept in memory between requests, and reload (requery) the persistent object in each request. In that way he solves the last-commit-wins problem. But he needs to solve the problem how to populate changes from UI to the loaded persistent objects but not unchanged (possible stale) states.
(2) Rizzo encountered LazyInitializationException. This is due to access to lazy loaded properties (so hibernate needs to load those properties) while there's no open session for hibernate to do that. The access is made by BeanItemContainer. This is price paid for using framework - something under the hood caused the problem, driver needs to lift the hood and examine engine made by others.
(3) Rizzo looked at the above article but is not comfortable with the HbnContainer deals with Hibernate Session.
(4) At last, Rizzo asked two questions in his opening post. i.) how to solve LazyInitializationException problem caused by vaadin container? ii.) how to populate only changes from UI to a persistent object freshly obtained by requery without repeated codes?
(5) Kim is experienced guy. He solve the first "LazeInitializationException" problem by not using BeanItemContainer but container with no relationship to beans. Then the programmer needs to populate that container (say IndexedContainer, for example) with hand-written codes. That's say a lot of boring codes handling two-way update.
(6) Kim uses session-per-request pattern so he don't have second problem. That way he only needs to reattach objects to open session. Kim don't have solution to the second question.
(7) Rizzo decide to write his own "BeanCopyContainer". Good for him!
(8) Kim said "remember that the states are stored on the server...". This is correct. However, it's stored in HttpSession, which shall be kept small - HttpSession can be persisted, transfered to another server "transparently", etc. Nevertheless, my understanding is that Vaadin application is a HttpSession, the states of various UI components are stored in HttpSession anyway. It may not go too far if store one hibernate session in Vaadin application.
(9) Rizzo finally took Kim's suggestion, using IndexedContainer. He also made a clone of BeanItemContainer and BeanItem to work with Hibernate.
III. Hibernate container and searching
http://vaadin.com/forum/-/message_boards/message/40285
(1) Bo want some really complex and flexible search function (one text box search). Later Bo extended HbnContainer class and gave the source code. It uses Hibernates Criterias.
VI. Lazy loading data - table | Vaadin + Spring + hibernate
http://vaadin.com/forum/-/message_boards/message/52519
(1) Yes, the key to the solution lies in Container
(2) Lazy loading occur at two level - first, the client (browser) component lazy-load data for display anyway; second, the Container implementation may lazy-load data;
(3) A JPAContainer is being planned
(4) HbnContainer can be referenced. Still, not mature enough to be called a "release". It seems that the best way is to make my own Container or kind of Bridge.