Hibernate issues

Last week I got a chance to use my new Hibernate materials.  Fortunately, since I was there to deal with them, they weren’t the major problem they should have been.  I understand this stuff a lot better now than when I wrote them, which I suppose is what a beta stage is all about.

(Or not.  I’d say the materials were probably more in an alpha stage.  You’re not supposed to add completely new functionality in the beta phase.)

There are, as it turns out, three important pages on the Hibernate Wiki that every Hibernate developer should read.

  1. Sessions and transactions
  2. Generic Data Access Objects
  3. Open Session in View

The Hibernate team obviously believes these are important, too, as they are all linked to each other.

The page on sessions and transactions explains that the SessionFactory.openSession method is, for all practical purposes, deprecated.  Okay, maybe that’s too harsh, but they continually refer to the “session per operation” anti-pattern, which is a pretty strong statement.

Instead, the preferred mechanism is to use SessionFactory.getCurrentSession, which of course relies on there being a current session in the first place.  One of my primary references for Hibernate, Pro Hibernate 3.0 by Minter and Linwood, demonstrates using a ThreadLocal object to store a session in a stand-alone application.  This turns out to be a sufficiently important mechanism that its actually built into the distribution.

All that is necessary is to go into the Hibernate configuration file (either hibernate.cfg.xml or hibernate.properties) and set two values:


hibernate.transaction.factory_class --> org.hibernate.transaction.JDBCTransactionFActory

and

hibernate.current_session_context_class --> thread

It turns out that the JDBCTransactionFactory is the default, so really only the second value needs to be set.  Doing so enables the code to use getCurrentSession everywhere, which also means the call to session.close in a finally block is also eliminated.

Of course, if an application uses JTA, the approach is somewhat different, but equally simple.  See the link for details.

The Open Session in View page implements this as the session per request mechanism.  They recommend using a servlet filter to get the current session, begin a transaction, and call the next filter in the chain.  When the response makes its way back, then call commit or rollback as necessary.

That’s easy enough to do.  Since a servlet filter implies a servlet container (i.e., an application server), you can also use JTA and JNDI lookups for the SessionFactory singleton.

Finally, we’ve got the generic DAO pattern.  I can totally understand the need for that, since creating DAOs can involve a lot of repetitive code.  Normally when I make a DAO I add in all the CRUD methods (create, retrieve, update, delete) in terms of the actual class.  For example, I would have a UserDAO class that would look like

public interface UserDAO {
  void addUser(User u);
  User findUserById(Integer id);
  List<User> findAllUsers();
  void updateUser(User u);
  void deleteUser(User u);
}

I might add overloads for id arguments, but that’s the basic structure.  The problem is, adding that for all entities is a pain, not to mention that the implementation classes are all very, very similar.

The generic DAO presented on the wiki page uses Java 5 generics to build a simpler approach which can be extended easily.  The methods they use are:

public interface GenericDAO(T, ID extends Serializable) {
  T findById(ID id, boolean lock);
  List<T> findAll();
  List<T> findByExample(T exampleInstance);
  T makePersistent(T entity);
  void makeTransient(T entity);
}

I like the makePersistent and makeTransient methods.  They replace any save, update, or delete methods in my DAOs.  When you look at their implementation of this interface in terms of an abstract class, makePersistent calls saveOrUpdate, makeTransient calls delete, and findById calls load.

(I don’t know why they call load rather than get.  The get method does the same thing, but if the entity doesn’t exist in the database then get returns null while load throws an exception.  I guess they want to throw an exception.  That’s easy enough to change.)

The other find methods actually call a protected method called findByCriteria(Criterion…).  It looks like if I want to have a findByName(String) method in my UserDAO, then when I extend GenericHibernateDAO and call findByCriteria with my own Restriction.eq(“name”,name) or some such.

Anyway, it’s a very interesting, reusable approach and simplifies the creation of DAOs enormously.  After all, if there are no special business related methods other than the CRUD methods, just extend the abstract class and you’re done.

One aside, though.  Acquiring a session is one of those “cross-cutting concerns” as Spring would say.  The DAOs shouldn’t care where or how a session is acquired, but they do need one in order to call load, saveOrUpdate, etc.  Therefore, the GenericHibernateDAO class adds in the setSession and getSession methods, which are invoked by a client somewhere.  That leads to a discussion of factories, or even dependency injection.

Hmm.  Lots to learn and lots to know.  Still, this seems to be the way the industry is going, so it’s all worth it either directly or as a collection of best practices.

I just wish all app servers (that means you, WebSphere) understood Java 5 generics.  While the syntax is ugly and awkward, the gain is too great to ignore, especially in cases like this.

Lookin’ for Java in all the wrong Faces…

I have such a cool job. I was emailing one of my training company clients about doing an introductory web class (HTML, some JSP, etc) out in Colorado in November. I was all set to agree to it when I got a phone call from my contact there.

“We found a local resource for that,” she said. “But we have another option the same week.”

“Oh?”

“How would you like to teach JavaServer Faces in Jamaica instead?”

Gee, let me think. Think, think, think. No wait, I don’t need to think.

“Yes!”

So, the week of 11/13 I’ll be in Jamaica teaching JSF. Maybe we can set up a wireless LAN on the beach…

Like I said, I have SUCH a cool job. 🙂

Sports on TV

Normally I try to stay away from making comments here that aren’t related to software development, but between the World Series and Monday Night Football, I have to say something.  I’ll keep it short and sweet though.

If somebody put Joe Theismann and Tim McCarver in the same booth to do commentary, my picture tube would explode.  Hopefully it would do it on its own.  If not, I’d have to destroy it, slowly, so it would hurt.  And don’t even bother bringing up Joe Buck.  I can’t even discuss him rationally.

New Hibernate version is here

The new Hibernate version, 3.2, is now available. The formal announcement came on 10/16.

I haven’t played with it a lot yet, of course, but one thing strikes me right away. If there are significant differences between 3.2 and the 3.1 version I’ve been using for months, I don’t see them. They may have made many fixed under the hood, but even the file system structure and the demos are all the same. At this point I don’t know what all the fuss was about.

The biggest lack from my point of view is that the Hibernate interfaces still don’t use Java 5 generics. In other words, query.list() still returns a List of Object, as I mentioned in an earlier post. That means that if I writes something like:

public List<User> findAllUsers() {
SessionFactory factory = ...;
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
Query q = session.createQuery("from User");
List<User> users = q.list();
tx.commit();
session.close();
return users;
}

then I have to add

@SuppressWarnings("unchecked")

to the method because of the cast from List to List<User>. It does work, though, so that’s good, but I think that worked with 3.1 as well.

The other thing I learned playing with the new distribution (and again this probably worked with 3.1 as well — I just didn’t realize it), is that I can use a parameterized Set as an attribute with the associated get and set methods and it all works. For example, if the User class has an attribute that is a Set of Role references, it’s okay for me to write

public class User {
Set<Role> roles = new HashSet<Role>();
public Set<Role> getRoles() { return roles; }
public void setRoles(Set<Role> roles) { this.roles = roles; }
...
}

It all comes out okay. I always thought I had to use a regular old Set rather than a parameterized one, but as they say, that turns out not to be the case. Good news.

Design Patterns

The class I’m teaching this week and next is a massive, customized combination of Design Patterns, JSTL, JSF, Spring, and Hibernate. It’s going to be an adventure.

Today, though, we were digging into patterns. Design patterns has usually been my favorite course to teach. If teaching is all about giving people the ability to do things they couldn’t do before, then patterns is one of those fundamentally enabling topics that helps all your code everywhere. It also helps people understand code from others that they’re reading, not to mention the Java APIs.

We talked mostly about Abstract Factory, Factory Method, Singleton, Strategy, Template Method, and Observer. Suffice it to say that it was a rather long day. I happen to like all of those and use them regularly. There are other creational patterns, too, like Builder and Prototype, that our materials didn’t dig into but I discussed with the students.

Yup, they’re fried, and it’s only Tuesday. It’s a standard dilemma. We have lots of material to cover, but it’s just hard to absorb that much that quickly. The students are roughly intermediate Java developers (with a wide standard deviation), but still sometimes the Java stuff itself is a bit of a challenge to them.

I brought up the Head First Design Patterns book and they seemed interested. I have mixed feelings about the whole Head First series. Kathy Sierra herself once wrote that people who criticize the books are often people who already know the technology. That’s probably true. The Head First EJB book was wonderful and got me through the Sun Certified Business Component Developer exam. On the other hand, I didn’t like the Head First Servlets and JSPs book at all. But, then again, I already knew servlets and JSPs when I read the book.

Personally, my favorite patterns book is still Applied Java Patterns by Stelting and Maasen, even though it’s getting a bit dated by now (published in Dec, 2001).

[The Mets blew a great opportunity. They had men on 2nd and 3rd with one out and didn’t score. They’re down to three outs left in order to keep from going down 3 games to 2.]

Incidentally, the students use IBM’s Rational Application Developer 6.0 in their jobs. That’s normally okay, but the design patterns materials I have use Java 5 generics, enhanced for loops, and other cool features. For this part of the class we’re using Eclipse 3.2 with the ever-popular MyEclipse 5.0 plug-in. That should really pay off later when we get back to the server side.

What happened to IBM’s tracking of Eclipse developments, anyway? When they first released WSAD 4.0 (WebSphere Studio Application Developer), they also released Eclipse 1.0. They stayed exactly 3 numbers apart for years after that, going to WSAD 5 (Eclipse 2), WSAD 5.1 (Eclipse 2.1), WSAD 5.1.2 (Eclipse 2.1.2), and even RAD 6.0 (Eclipse 3.0). Now Eclipse has moved to 3.1 and then to 3.2 and we’ve gotten nothing from IBM. I’ve heard rumors of a RAD 7, but I don’t know what that’s all about.
Okay, the move to Eclipse 3.1 was big and difficult because that’s the first version that really worked with Java 5. WebSphere still doesn’t get Java 5 at all, which is one of the many reasons I tend to prefer JBoss (now a division of Red Hat).

Speaking of annoyances, Hibernate 3.1 works with Java 5, but doesn’t use Java 5 generics. As ugly and awkward as the generics implementation is (try making a Map where the values are also a List some time), I find it very annoying that I can’t use generics in my code because query.list() and criteria.list() methods both return List of Object. It’s back to casting again, plus I can’t use the for each loop.

Hibernate 3.2 is a hairs-breadth from release. I hope they’ve fixed that, but the betas don’t seem to show it.

The Mets went one-two-three in the 9th. So much for that. As long as the Yankees have been eliminated, I’m happy. 🙂

Rumble, rumble (or so they tell me)

I’m in Winston-Salem, NC this week and next.  I’m working on the Hibernate materials this evening with the NLCS game on in the background (top of the 8th, St. Louis leading the Mets 4 — 2).  Every so often the TV beeps at me as the local station begins a slow crawler along the bottom.

It seems we had a massive earthquake here early this morning.  It measured a whole 2.4 on the Richter scale.  Woo.  We’ve even had a couple of major aftershocks this evening, measuring 2.1 and 1.4.

Who knows?  Maybe if I’d been watching a pot of still water at the time I might have seen it vibrate.  Or not.  Good thing the TV keeps reminding me about it, though.

Quick thoughts again

Some quick items while I’m working on the Hibernate materials (or is that avoiding working on the Hibernate materials?):

  1. My post last week about Steve Yegge’s extended blog entry on “good” vs. “bad” agile development was done too quickly.  By that I mean I reacted to an early part of his blog before reading the whole thing.  What I said was okay, since it reflected my own experience, but after I finished the actual post I realized something important.  That post is fantastic.  Mr. Yegge really knows what he’s talking about.  If you haven’t read it, please find time to do so.  His post may be one of the best extended posts about the software development process I’ve ever read.
  2. And by the way, it sounds like working at Google is a dream come true for software developers.  I wonder how long it will last.  I also wonder how to make it work myself if I ever wind up hiring employees.
  3. Hibernate is very interesting, especially the way detached objects remove the need for the Data Transfer Object (DTO) (anti-)pattern.
  4. I’m just about booked for the rest of the year already.  Whoa.  Maybe I’m not charging enough… 🙂
  5. The Yankees quick, ignominious exit from the playoffs at the hands of the Tigers give me a great feeling of schadenfreude.  I would feel sorry for them, but I just can’t.
  6. Speaking of complete and utter irrationality, I’d bet anything that the Yankees will shop A-Rod around.  That’s insane, but might be inevitable.  Given the Red Sox recent history with Manny Ramirez, I’m just waiting for the first rumors of a one-for-one swap.  We’ll see.  It should be an interesting off-season for the hot stove league.

Back to the salt mines…

%d bloggers like this: