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

Actually, on further reflection, because you can only work with a Query while you've got an active Session, the methods offered by the DAOs already work the best way they possibly can. You're always going to have to do your own session management if you want to work with the query the way I do in this example. You could embed the session management into the business logic provided in "your" half of the DAO, though, which would give you the best of both worlds. That's another reason the split-class model offered by Hibernate Synchronizer is so useful. I explore this insight a bit below.



Anyway, here's the code I first came up with, morally quite equivalent to that on pages 48-49 of the book:

package com.oreilly.hh;

import java.sql.Time;
import java.util.ListIterator;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Query;
import net.sf.hibernate.Session;

import com.oreilly.hh.dao.TrackDAO;
import com.oreilly.hh.dao._RootDAO;

/**
 * Use Hibernate Synchronizer's DAOs to run a query
 */
public class QueryTest3 {

    public static void main(String[] args) throws HibernateException {
        // Load the configuration file and get a session
        _RootDAO.initialize();
        Session session = _RootDAO.createSession();

        try {
            // Print the tracks that will fit in five minutes
            Query query = session.getNamedQuery(
                TrackDAO.QUERY_COM_OREILLY_HH_TRACKS_NO_LONGER_THAN);
            query.setTime("length", Time.valueOf("00:05:00"));
            for (ListIterator iter = query.list().listIterator() ;
                 iter.hasNext() ; ) {
                Track aTrack = (Track)iter.next();
                System.out.println("Track: \"" + aTrack.getTitle() +
                                   "\", " + aTrack.getPlayTime());
            }
        } finally {
            // No matter what, close the session
            session.close();
        }
    }
}

One nice feature that TrackDAO does give us is a static constant by which we can request the named query, eliminating any chances of run-time errors due to typos in string literals. I appreciate that! Setting up and executing a Run configuration for this test class produces the output I'd expect, as shown in Figure 22.

Figure 22
Figure 22. The query results in Eclipse's console view

As I noted above, after getting this class working, I realized there was a better way to approach it, given the model offered by Hibernate Synchronizer. Here's what our TrackDAO object would look like if we moved the query inside of it, which is where it really belongs, given that the named query is a feature of the mapping file associated with that data access object:

package com.oreilly.hh.dao;

import java.sql.Time;
import java.util.List;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Query;
import net.sf.hibernate.Session;

import com.oreilly.hh.base.BaseTrackDAO;

/**
 * This class has been automatically generated by Hibernate Synchronizer.
 * For more information or documentation, visit The Hibernate Synchronizer page
 * at http://www.binamics.com/hibernatesync or contact Joe Hudson at joe@binamics.com.
 *
 * This is the object class that relates to the TRACK table.
 * Any customizations belong here.
 */
public class TrackDAO extends BaseTrackDAO {

    // Return the tracks that fit within a particular length of time
    public static List getTracksNoLongerThan(Time time)
        throws HibernateException
    {
        Session session = _RootDAO.createSession();
        try {
            // Print the tracks that will fit in five minutes
            Query query = session.getNamedQuery(
                QUERY_COM_OREILLY_HH_TRACKS_NO_LONGER_THAN);
            query.setTime("length", time);
            return query.list();
        } finally {
            // No matter what, close the session
            session.close();
        }
    }
} 

This is nice and clean, and it simplifies the main() method in QueryTest3 even more:

    public static void main(String[] args) throws HibernateException {
        // Load the configuration file and get a session
        _RootDAO.initialize();

        // Print the tracks that fit in five minutes
        List tracks = TrackDAO.getTracksNoLongerThan(Time.valueOf("00:05:00"));
        for (ListIterator iter = tracks.listIterator() ;
             iter.hasNext() ; ) {
            Track aTrack = (Track)iter.next();
            System.out.println("Track: \"" + aTrack.getTitle() +
                               "\", " + aTrack.getPlayTime());
        }
    }

Clearly this is the approach to take when working with named queries and Hibernate Synchronizer. A quick test confirms that it produces the same output, and it's much better code.

Whether or not you want to use Hibernate Synchronizer to generate its own style of data access objects, there is one last major feature to explore.

Editing Mappings

One of the main attractions of Hibernate Synchronizer is its specialized editor for mapping documents. This editor can be configured to automatically regenerate the associated data objects whenever you save files, but that's just a final touch; you might want to use the editor even if you're not using the plugin's code generator. It gives you smart completion of mapping document elements, and a graphical outline view in which you can manipulate them, as well.

There is a trick to getting the editor to work for you, though, at least if you're starting from the downloaded source code from my Developer's Notebook. In the download, the mapping documents are named with the extension ".hbm.xml," and the editor is only invoked for files ending with ".hbm". In theory, you can configure the extension mappings within Eclipse so that both extensions use the plugin's mapping document editor, but I wasn't able to get that to work, and I saw that someone else on the support forum had the same problem. So, at least for now, your best bet may be to rename the files. (If you're going to stick with Ant-based standard code generation, be sure to update the codegen target in build.xml to use the new extension, too.)

As soon as I renamed Track.hbm.xml to Track.hbm, its icon in the Package Explorer was updated to look like the Hibernate logo, and the default editor became the plugin's, as shown in Figure 23. For whatever reason, the other Hibernate Synchronizer options (as shown in Figure 17) are available with either extension, but the editor is available only with the shorter version.

Figure 23
Figure 23. The contextual menu for a Hibernate mapping document (with the extension ".hbm")

The editor has context-sensitive completion support for all of the elements you're adding within the mapping document. Figure 24 shows a couple of examples, but no screen shots can really capture the depth and usefulness of a feature like this; I'd very much encourage you to install the plugin and play with it yourself for a while. You will quickly see how helpful it can be in working with mapping documents.

Figure 24

Figure 25
Figures 24 and 25. Completion assistance in the mapping document editor

The outline view, shown in Figure 26, gives you a graphical view of the hierarchy of classes, their mapped elements, named queries, and the like that are present in your mapping document, as well as giving you a menu offering a few wizards to help you create new ones.

Figure 26 Figure 27

Figures 26 and 27. The mapping editor's outline view, and the "Add property" wizard

The contextual menu within the editor itself also offers a Format Source Code option you can use to clean up and re-flow the document. There are already many neat and useful features in this editor, and it'll be interesting to see how it grows in the future. My only complaint (and a minor one at that) is that this editor uses a very different approach to helping you manage quotation marks when you complete XML attributes than the JDT does in Java code. Switching back and forth between them can be somewhat disorienting. (The way the JDT works takes a little getting used to itself, but once you start trusting it, it's almost magical.)

Pages: 1, 2, 3, 4, 5

Next Pagearrow