ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Working with Hibernate in Eclipse
Pages: 1, 2, 3, 4, 5

Generating Code

This is probably the part you've been waiting for. What cool stuff can we do? Well, right away there is a new contextual menu entry available for Hibernate mapping documents.



If you right-click (or control-click) on one, you get a number of Hibernate-related choices (Figure 17), including one to synchronize. This is a manual way to ask Hibernate Synchronizer to generate the data access objects associated with the mapping document.

Figure 17
Figure 17. Synchronizer choices for mapping documents

The Add Mapping Reference choice is also useful: it adds an entry to the main Hibernate configuration file telling it about this mapping document, so you don't need to put anything in your source code to request that the corresponding mapping gets set up. For now, let's look at the result of choosing Synchronize Files.

This is where things start to get interesting. We end up with two new sub-packages, one for the "base" data access objects that Hibernate Synchronizer "owns" and can rewrite at any time, and one for our business objects that subclass these DAOs, which will not get overwritten, and give us an opportunity to add business logic to the data class (shown in Figure 18).

Figure 18
Figure 18. The synchronized data access objects, showing our editable subclass

There are many more classes generated this way than by using the normal Hibernate code generation facilities, which has advantages, as well as some potential disadvantages, which I discuss later in the Trade-Offs section. Note also that in the properties configuration for your project, you can choose which of these classes get generated for you, as well as the package structure into which they are generated. I'd demonstrate this, but the current release of the plugin has a bug which blocks access to this configuration interface on Mac OS X. A fix has been made, but not yet released.

Based on the examples on the Hibernate Synchronizer page, I put together the following class to try inserting some data into the music database using these new data access objects. It's quite similar to the version using the standard Hibernate code generator (on pages 39-40 of Hibernate: A Developer's Notebook) and even simpler because the classes generated by Hibernate Synchronizer create and commit a new transaction for each of your database operations, so you don't need any code to set one up in simple situations like this. (There are ways of doing so if you need to have a group of operations operate as a single transaction, of course.) Here's the code for the new version:

package com.oreilly.hh;

import java.sql.Time;
import java.util.Date;
import net.sf.hibernate.HibernateException;
import com.oreilly.hh.dao.TrackDAO;
import com.oreilly.hh.dao._RootDAO;

/**
 * Try creating some data using the Hibernate Synchronizer approach.
 */
public class CreateTest2 {

    public static void main(String[] args) throws HibernateException {
        // Load the configuration file
        _RootDAO.initialize();
        
        // Create some sample data
        TrackDAO dao = new TrackDAO();
        Track track = new Track("Russian Trance", "vol2/album610/track02.mp3",
            Time.valueOf("00:03:30"), new Date(), (short)0);
        dao.save(track);
        
        track = new Track("Video Killed the Radio Star",
            "vol2/album611/track12.mp3", Time.valueOf("00:03:49"), new Date(),
            (short)0);
        dao.save(track);
        
        // We don't even need a track variable, of course:
        dao.save(new Track("Gravity's Angel", "/vol2/album175/track03.mp3",
            Time.valueOf("00:06:06"), new Date(), (short)0));
    }
}

Having Eclipse around while I was writing this was very nice. I'd forgotten how much I missed intelligent code completion while I was writing the examples for the book, and there are several other things the JDT helps with too.

To run this simple program within Eclipse, we need to set up a new Run configuration. Choose Run -> Run... with CreateTest2.java as the currently active editor file. Click on New and Eclipse figures out that we want to run this class in our current project, because we created it with a main() method. The default name it assigns, CreateTest2, is fine. The screen will look something like Figure 19. Click Run to try creating some data.

Figure 19
Figure 19. Ready to run our creation test in Eclipse

If you've been exactly following along on your own, you'll find that this first attempt at execution fails: Hibernate complains that the configuration file contains no mapping references, and at least one is required. Ah ha! So that's what XMLBuddy was warning about with the yellow underline near the bottom of Figure 16. We can easily fix this by right-clicking on the Track.hbm.xml mapping document in the Package Explorer view and choosing Add Mapping Reference in the new Hibernate Synchronizer submenu. That makes XMLBuddy happy, and allows the run to get further. Unfortunately, not as far as we might like, though. The next error was a complaint about not being able to find the JTA UserTransaction initial context in JNDI. It turned out I wasn't the only person having this problem; it was discussed in a forum thread, but no one had yet found a solution.

Since I knew I didn't need to use JTA, I wondered why Hibernate was even trying. I opened up the Hibernate configuration file (Figure 16) and looked for anything suspicious that Hibernate Synchronizer had put there. Sure enough, there were some lines that looked like prime suspects:

 <property name="hibernate.transaction.factory_class"> 
       net.sf.hibernate.transaction.JTATransactionFactory 
 </property> 
 <property name="jta.UserTransaction"> 
       java:comp/UserTransaction 
 </property> 

Once I tried commenting these out and running again, the third time was indeed the charm. My run completed with no errors, and my data appeared in the database. Hurrah! Running the trusty ant db target (explained in Chapter 1 of the Developer's Notebook) reveals the data in all its (admittedly simple) glory, as shown in Figure 20. If you're doing this yourself, be sure to start with an ant schema to create the database schema or empty out any test data that may be there from previous experimentation.

Figure 20
Figure 20. The data created by our test program

Note that you can run Ant targets from within Eclipse by right-clicking (or control-clicking) on the build.xml file within the Package Explorer, choosing Run Ant and picking the target using an Eclipse dialog. Pretty cool.

Figure 21
Figure 21. Running Ant from within Eclipse

Getting data back out using queries is pretty straightforward, although this time it's a lot closer to the same code you'd use with the ordinary Hibernate-generated data access classes. Even though Hibernate Synchronizer generates a number of helper methods for working with named queries, I don't think any of them is particularly useful, because they all insist on running the query and returning the list of results, rather than giving you the Query object to work with yourself. That prevents you from using any of Query's convenient type-safe parameter setting methods. Because of that, I decided to stick to having the _RootDAO object give me a Hibernate Session to work with the "old fashioned" way. In fairness, I think I could edit the templates used by Hibernate Synchronizer to generate any methods I'd like, and would almost certainly look into doing that if I was going to undertake a project with it.

Pages: 1, 2, 3, 4, 5

Next Pagearrow