Creating Service Beans |
Our next objective will be to use our configured MySQL database to store some information. We will store a data structure representing the guesses that visitors have submitted. Create a package named edu.jhu.cs.oose.j2ee.example.vo in your VO project's root package and put the following class inside of it.
This is a fairly simple class. Note that it has an implicit no-args constructor; this is necessary for Hibernate to be able to use it.
Next, we will add a unique ID number to the class since it doesn't have one of its own. While Java objects usually don't need such an identifier (since they have a unique location in memory), persisted objects typically do. A different ID can be used if one is handy (such as a username or a student ID code), but in this case we must create an ID field simply to be able to tell Guess objects apart. Add an id field to the class so that it now looks like this:
Next, we will add the JPA annotations which allow us to describe the persistence properties of the class to Hibernate. An application exclusively using JPA annotations is not dependent on the Hibernate library, but most practical applications need to take advantage of some features not yet standardized (like Hibernate queries or specifications of the maximum length of strings). After annotating our class, we have the following.
These annotations have the following effect:
In some configurations, we would now have to inform Hibernate that this is a persisted class. In this tutorial's configuration, however, this is addressed by the packagesToScan property of the sessionFactory bean that we set up in test-servlet.xml. That property tells Hibernate to scan the package and all of its subpackages for @Entity-annotated classes. As a result, the mere existence of the class is enough.
We have now configured the object we wish to be able to save to the database; next, we must configure a repository for these objects (sometimes also known as a DAO - a data access object). You may create as many or as few repositories as you wish (much like service and controller beans); it's generally best to create one repository for each type of object or related group of objects. In this case, we will create a single repository for persisting Guess objects.
We start by creating a package inside of the application root package of our data project. This package is called edu.jhu.cs.oose.j2ee.example.repositories. Inside of that package, we create an interface named GuessRepository and a class named GuessRepositoryImpl.
The SessionFactory property of the above repository implementation is the object which is used to create and manage Hibernate sessions in the J2EE application. We configured this bean in the Spring XML configuration, which means that the @Autowired annotation will ensure that it is wired in correctly. This object is also used by the transaction manager, which is discussed below.
This particular repository implementation is about as contrived as the rest of the application; it performs a very simplistic function, merely delegating its call to the session factory. More complex repositories, however, may have routines for saving or deleting whole groups of objects, finding all objects which match a certain set of criteria, and so on.
We now modify the GuessService bean to use the repository to save each guess it receives.
The newest addition above is the @Transactional annotation. Spring uses this annotation to signal that the method's body must run within a consistent transaction. By default, the transaction is rolled back if a RuntimeException subclass is thrown and commits the transaction in all other cases (including when checked exceptions are thrown). This behavior can be adjusted by passing arguments to the @Transactional annotation.
Launching the application and submitting guesses will now save objects to the database. Consider, for example, the following examination of the MySQL database after guesses have been applied.
It is important to note that the alignment above is not a mistake; it is the effect of the correct cell in the third row having a different (unprintable) value from the first two. Hibernate is using this encoding to distinguish between true and false values.
Creating Service Beans |
Written by Zachary Palmer with help from Varun Sharma. Corrections and suggestions are welcome; please e-mail zachary dot palmer xX att Xx jhu.edu