Prova

6
09/01/12 01:19 Using Hibernate with Vaadin - Wiki Page 1 of 6 https://vaadin.com/wiki/-/wiki/Main/Using+Hibernate+with+Vaadin/pop_up?_36_viewMode=print Print Using Hibernate with Vaadin Using Hibernate in Toolkit application, Basic CRUD actions for persistent POJO Check out related source code with subversion ( svn co http://dev.vaadin.com/svn/incubator/hbncontainer/ ) or view it with trac http://dev.vaadin.com/browser/incubator/hbncontainer/. Download the latest version as a Vaadin add-on from the Vaadin Directory ( http://vaadin.com/addon/hbncontainer ) The project in incubator currently has a prototype of using associations. The article is outdated on that part. Hibernate is the de facto standard when it comes to Java and Object Relational Mapping. Since version 3 onwards one can actually drop the de factor part as Hibernate 3 implements Java Persistency API with some optional packages. Hibernate is backed by a strong support from both commercial players and open source community. It is an important part of popular JBoss Application Server. As an open source project with an industry proven maturity, Hibernate makes a perfect combo with IT Mill Toolkit. Hibernate is in a key role in many projects built or supported by IT Mill. The way Hibernate is used varies a lot due different kinds of architectures and requirements. Largest questions are usually how to work with Hibernate session, transactions and how to tie entity beans into toolkit components. In this article and example application I'll show you how to implement session-per-request pattern for Hibernate session handling and present some patterns to do CRUD actions of a simple entity bean. As I'm a sport fanatics, instead of storing cats and other mammals to DB we'll build a simple !WorkoutLog application to store the details of our jogging sessions. Download the source package to see full source code. Note that this is not trying to be a yet another Hibernate tutorial. Although we'll stay in rather basic tricks, I expect the reader to have some experience on ORM and IT Mill Toolkit. The purpose of this tutorial is to show an example how to do simple Hibernate session handling in Toolkit application and explain some patterns how to entity objects can be tied into GUI. Preparing the project # If you want want to learn by doing, it is time to put your hands on dirt. Create a new web application project in you favorite IDE, throw in latest toolkit.jar and all needed hibernate related libraries. Prepare your database and configure Hibernate. Combo I chose when writing this article was Eclipse, WTP and MySQL 5, but any option should be fine. You'll find help and step-by-step instructions for these tasks form hibernate.org and dev.toolkit.com. If you want to get started really easily, check out the Eclipse project from svn repository. This is done simply with subclipse plugin or via command line svn co http://dev.vaadin.com/svn/incubator/hbncontainer/. The project containtains embedded database( HSQLDB ), all needed required libraries and the source code for the example project itself. That is an easy way to start experimenting with Toolkit and Hibernate. You will also need a servlet container, Tomcat is a good option.

description

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam id dolor id nibh ultricies vehicula ut id elit. Maecenas sed diam eget risus varius blandit sit amet non magna. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Cras mattis consectetur purus sit amet fermentum.

Transcript of Prova

Page 1: Prova

09/01/12 01:19Using Hibernate with Vaadin - Wiki

Page 1 of 6https://vaadin.com/wiki/-/wiki/Main/Using+Hibernate+with+Vaadin/pop_up?_36_viewMode=print

PrintUsing Hibernate with VaadinUsing Hibernate in Toolkit application, Basic CRUD actions for persistent POJO

Check out related source code with subversion ( svn co http://dev.vaadin.com/svn/incubator/hbncontainer/ ) or view it with trachttp://dev.vaadin.com/browser/incubator/hbncontainer/. Download the latest version as a Vaadin add-on from the Vaadin Directory (http://vaadin.com/addon/hbncontainer )

The project in incubator currently has a prototype of using associations. The article is outdated on that part.

Hibernate is the de facto standard when it comes to Java and Object Relational Mapping. Since version 3 onwards one can actually drop the de factorpart as Hibernate 3 implements Java Persistency API with some optional packages. Hibernate is backed by a strong support from both commercialplayers and open source community. It is an important part of popular JBoss Application Server.

As an open source project with an industry proven maturity, Hibernate makes a perfect combo with IT Mill Toolkit. Hibernate is in a key role in manyprojects built or supported by IT Mill. The way Hibernate is used varies a lot due different kinds of architectures and requirements. Largest questions areusually how to work with Hibernate session, transactions and how to tie entity beans into toolkit components.

In this article and example application I'll show you how to implement session-per-request pattern for Hibernate session handling and present somepatterns to do CRUD actions of a simple entity bean. As I'm a sport fanatics, instead of storing cats and other mammals to DB we'll build a simple!WorkoutLog application to store the details of our jogging sessions. Download the source package to see full source code.

Note that this is not trying to be a yet another Hibernate tutorial. Although we'll stay in rather basic tricks, I expect the reader to have some experience onORM and IT Mill Toolkit. The purpose of this tutorial is to show an example how to do simple Hibernate session handling in Toolkit application and explainsome patterns how to entity objects can be tied into GUI.

Preparing the project #

If you want want to learn by doing, it is time to put your hands on dirt. Create a new web application project in you favorite IDE, throw in latest toolkit.jarand all needed hibernate related libraries. Prepare your database and configure Hibernate. Combo I chose when writing this article was Eclipse, WTP andMySQL 5, but any option should be fine. You'll find help and step-by-step instructions for these tasks form hibernate.org and dev.toolkit.com.

If you want to get started really easily, check out the Eclipse project from svn repository. This is done simply with subclipse plugin or via command linesvn co http://dev.vaadin.com/svn/incubator/hbncontainer/. The project containtains embedded database( HSQLDB ), all needed required libraries and thesource code for the example project itself. That is an easy way to start experimenting with Toolkit and Hibernate. You will also need a servlet container,Tomcat is a good option.

Page 2: Prova

09/01/12 01:19Using Hibernate with Vaadin - Wiki

Page 2 of 6https://vaadin.com/wiki/-/wiki/Main/Using+Hibernate+with+Vaadin/pop_up?_36_viewMode=print

Tomcat is a good option.

As I hate all xml configuration I created DB mappings with annotations. Below is the one and only entity class we'll be using in this example. Create it inand possibly test your Hibernate configuration with a simple test application.

#!java@Entitypublic class Workout { @Id @GeneratedValue(strategy=GenerationType.AUTO) private Long id; private Date date = new Date(); private String title = " -- new workout -- "; private float kilometers;

public Workout() {}

public Long getId() { return id; }

private void setId(Long id) { this.id = id; }

public Date getDate() { return date;

}

public void setDate(Date date) { this.date = date; }

public String getTitle() { return title; }

public void setTitle(String title) { this.title = title; }

public float getKilometers() { return kilometers; } public void setKilometers(float kilometers) { this.kilometers = kilometers; } }

Also create a new Tookit application, configure it in web.xml.

Using session-per-request pattern #

Proper session handling in Hibernate backed applications is often the most difficult problem. Use cases vary from by architecture and load. Hibernate isknown to be quite strict on session and transaction handling, so to save yourself from a headache, I'd suggest you to make it right. There is a lot's of gooddocumentation about different session handling patterns in hibernate.org.

Using session-per-request pattern is often a safe bet for Toolkit application. It is maybe the most common pattern among all Servlet based applications.When doing data manipulation we'll use the same session during the whole request and in the end of the request make sure that session and transactionis properly finalized. When implemented properly, session-per-request pattern guarantees that number of Hibernate sessions is in control, sessions areproperly closed and sessions are flushed regularly. A good combo of characteristics for a multi-user web application.

By Toolkits nature, session-per-request pattern is actually kind of wrong. Toolkit is a general purpose GUI framework and programmer does not need to

Page 3: Prova

09/01/12 01:19Using Hibernate with Vaadin - Wiki

Page 3 of 6https://vaadin.com/wiki/-/wiki/Main/Using+Hibernate+with+Vaadin/pop_up?_36_viewMode=print

By Toolkits nature, session-per-request pattern is actually kind of wrong. Toolkit is a general purpose GUI framework and programmer does not need tothink about requests and responses at all. Actually Toolkit applications and components don't know nothing about requests. It its the web terminal thatdoes all the web magic. Another option is to use session-per-application or even session-per-transaction like one would do with SWING or other destopapplication. Always evaluate your requirements, use cases and available computing resources to have the optimal session handling pattern.

To ensure that we are using only one Hibernate session per http request is the easy part. We can use Hibernates getCurrentSession() to retrieve threadlocal session instance. As we always want to actually use the session I build a helper method that will also begin a database transaction. In our!WorkoutLog we will always be using this method to get session reference.

#!java /** * 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; }

Closing is bit more tricky. One way around would be to use a servlet filter. You can find examples of this from hibernate.org. But we'll keep toolkitsterminal independence in mind and don't pollute our program with servlet specific code. To properly implement session-per-request pattern we'll need tofamiliarize ourselves to a feature in Toolkits terminal. Ideally toolkit programmer don't need to care about terminal at all, but now we need to hook somelogic into the end of (http) request that don't exist for the application. For the pattern it is essential that session finalization is done always and and after allhibernate related stuff is done. With event based programming model there is no way we can detect the last database action in the actual program code.

The feature we need is !TransactionListeners. !TransactionListeners are attached to !ApplicationContext which corresponds to http session in our currentweb terminal. !TransactionListeners are notified right before and right after the clients state is synchronized with server. The transaction end is what weneed here. I'll attach the transaction listener in the applications init() like this:

#!java

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) {

} });

In closeSession() the usual Hibernate sessions finalization is done.

#!java private void closeSession() { Session sess = HibernateUtil.getSessionFactory() .getCurrentSession(); if(sess.getTransaction().isActive()) { sess.getTransaction().commit(); } sess.flush(); sess.close(); }

Page 4: Prova

09/01/12 01:19Using Hibernate with Vaadin - Wiki

Page 4 of 6https://vaadin.com/wiki/-/wiki/Main/Using+Hibernate+with+Vaadin/pop_up?_36_viewMode=print

The sequence diagram below shows how Session handling works with this pattern during one (http) request. It is an imaginary server visit that fires toevent listeners. The first one does some listing and the latter re-attaches detached pojo. Note that the second database/Hibernate action uses the sameSession object as the first one. Note that function names are not real ones, but trying to describe the process better.

Due Toolkit applications do have state, pattern can be defined more strictly as a session-per-request-with-detached-objects pattern. As the sessioncloses quite often, our entity objects are most likely detached by the time we are updating them. So when we have our changes to entity object done, it istime to re-attach it to current session to persist changes into database. An example of that is below:

#!java run.setDate((Date) date.getValue()); run.setKilometers(Float.parseFloat(kilomiters.getValue().toString())); run.setTitle((String) title.getValue()); getSession().merge(run);

Page 5: Prova

09/01/12 01:19Using Hibernate with Vaadin - Wiki

Page 5 of 6https://vaadin.com/wiki/-/wiki/Main/Using+Hibernate+with+Vaadin/pop_up?_36_viewMode=print

Attaching POJO's UI #

In this chapter I'll discuss briefly some options to implement basic CRUD (Create, Read, Update, Delete) actions for our DB backed Workout objects.

Listing Objects #

If you are learning by doing, I'd suggest that you manually insert some rows to your db at this point. Listing an empty database will be quite boring.

The most natural way to list our simple Workout object is to put them into Table component. To do this there is an easy way and an the right way. We'llstart with the easy one, but I suggest to use the latter in real applications. The code below (the "easy" way) is not in the !WorkoutLog app at all, but youcan try it if you want.

#!java // prepare tables container table.addContainerProperty("date", Date.class, null); table.addContainerProperty("kilometers", Float.class, null); table.addContainerProperty("title", String.class, null); // list all Workouts List workouts = getSession().createCriteria(Workout.class).list(); for (Iterator iterator = workouts.iterator(); iterator.hasNext();) { Workout wo = (Workout) iterator.next(); // add item to table and set properties from POJO Item woItem = table.addItem(wo.getId()); woItem.getItemProperty("date").setValue(wo.getDate()); woItem.getItemProperty("kilometers").setValue(wo.getKilometers()); woItem.getItemProperty("title").setValue(wo.getTitle()); }

In the above example we are using Table's default container, IndexedContainer. It is a good general purpose container, but using it always is not a goodoption. You have to load the data into it by yourself and configure properties etc. It also stores everything in memory. In our example it may start to be aproblem be a problem if you do three workouts everyday, live 100 years old and memory chips don't get cheaper in the future. But in real application wemight really have millions of records in DB. I really wouldn't suggest to load that table into memory anymore.

As you may guess the way is to build our own container for Workouts. Building good containers is one of the most difficult tasks in Toolkit programming.There are number of different sub interfaces one might want to implement and a whole bunch of methods code. Luckily one can't safely throw!UnsupportedOperationExeception for many of those. It is a boring tasks, but it often pays it back later. When you have your container ready, it hides lotsof DB access from program logic and can be used for many components (Selects, Trees, Tables etc). With your own customized container you can alsotune it to work as you want (memory-consumption versus speed etc).

As building a full-featured is not in the scope of this article, it is time to throw in a nice helper class called !HbnContainer. It takes a Hibernate entity classand a strategy to get Hibernate session in its constructor. It is indexed, ordered, sortable, had a limited supports adding/removing items and even ought tobe fairly well scalable (by number of rows in DB). It is not part of Toolkit as we don't consider it ready for framework yet, but we hope to have somethingsimilar in the core Toolkit in later releases. But feel free to use it in you own projects.

With !HbnContainer loading table with Workouts simplifies quite a bit. We need to implement !HbnContainer.!SessionManager interface, but it is rathereasy task as we already have getSession named function in our !WorkoutLog. Create and add table to your application, load its content with followingcode snippet and you should have a Workout listing on your screen.

#!java table.setContainerDataSource(new HbnContainer(Workout.class, this));

Creating workouts #

Now that we have listing we might want to add some rows via our web interface. To create a new Workout instance and store it in to DB we have to dothe usual Hibernate stuff: instantiate POJO and attach it to session. But as I hinted earlier, having a good container will help us to do it even simpler.!HbnContainer supports adding items with the most simplest method addItem().

If you look into the implementation, it does all the usual Hibernates stuff and returns items generated identifier. In addition this it also notifies appropriatelisteners that the content of table has changed. So by using containers addItem() method instead of doing DB persist ourselves we don't need to worryabout UI updates. Table listens to its container changes and changes gets sent to web browsers.

Page 6: Prova

09/01/12 01:19Using Hibernate with Vaadin - Wiki

Page 6 of 6https://vaadin.com/wiki/-/wiki/Main/Using+Hibernate+with+Vaadin/pop_up?_36_viewMode=print

Add Child Page , 2 Attachments

Your Rating Average (9 Votes)

Comments

about UI updates. Table listens to its container changes and changes gets sent to web browsers.

Updates and deletes #

Building an editor for our Workout object is a straight forwarded coding task. You may organize your code just like you want. !WorkoutEditor class is asimple example implementation that shows and editor in floating window. It has fields for workouts properties and it can be loaded with Workout instanceor with an identifier. In !WorkoutLog I attached a !ValueChangeListener into table to open editor when user clicks a row in table. Save and delete buttonsin !WorkoutEditor delegates work back to methods in main application. Delete uses containers method and behind the scenes a normal Hibernate objectdeletion. When saving we just reattach detached object using merge().

To avoid "monkey-coding" I'll show one can to use toolkits advanced features to automatically create editable fields for items. The !WorkoutEditor classcould have created its fields automatically by using appropriate Item and a Form component. Also Table supports automatic field generation, so why notedit workouts directly in our main object listing?

All we need to do is to use setEditable() method. In !WorkoutLog there is a button that toggles this feature. Clicking it make table editable, clicking it againshows data only. Can't imagine any simpler way to do the 'U' part of CRUD.

Both Form and Table components use FieldFactory interface to automatically create fields for Items properties. There is a simple default factory that youalmost certainly want to modify for your needs. As an example I extended it to set proper resolution for date field and also did some other fine tuning.

If you investigate the code a bit you might wonder how the database is updated now as we don't seem to call merge() or any other method to re-attachedPOJO. When field is updated it knows only about its underlaying Property. In this case it is !EntityItemProperty built by !HbnContainer. Field calls itssetValue() method and that is where the underlaying POJO is re-attached into Hibernate session.

Adding custom columns to !HbnContainer #

This last bonus chapter is bit out of scope of the article. But as updating is so easy in Table we could ditch our !WorkoutEditor. But then arises a questionhow to implement deletion. An option is to use Tables selection feature and "Delete selected" button. Another one is to use context menu option. This isalso done in !WorkoutLog. Both are good options, but someday someone will be asking how to add delete button on each row. So lets discuss that rightaway.

Ideologically this is adding a new property to our items. We definitely don't want to pollute our entity object by adding "public Button getDelete()" to ourWorkout object. The right place to implement this is in custom Container and Item. I implemented an example of this by extending !HbnContainer to!WorkoutListingWithSteroids. It adds a column "actions" (or container property if we are talking "Toolkit") which is a layout containing two buttons.

Another possibly little bit easier method is to use recently introduced feature in Table component called ColumnGenerator. !WorkoutLog (in svn) has anexample of this method too.

Check out the example code if you want this kind of behavior.

Summary #

Popular open source ORM tool Hibernate is a perfect companion for IT Mill Toolkit. Finding the right way to handle session in your application is a oftenthe most critical task. Session-per-request pattern is a safe choice for Toolkit application, but not the only option. DB backed entity objects are used in ausual manner. To use more advanced features of toolkit, you'll want to use a custom built container-item-property set. ORM is never easy, but it is not a

rocket science if you use tested industry proven patterns. And if your application is going to be a big or old, I can guarantee that you will have a nice ROIfor hours you spend on it (ORM).

41862 Views