Thursday, September 10, 2009

Prefer getters to accessors in Hibernate domain object

I ran into something tricky today. I have a domain object.

public class User {
private String firstName;
private String lastName;

// getters and setters

// a utility method
public String getFullName() {
return this.lastName + ", " + this.firstName;
}
}

Everything looks reasonable except the full name is always "null, null" at runtime. Then I realized Hibernate has lazy loading. "this.lastName" and "this.firstName" are not populated until the getter methods are called. It worked fine after switching to getters.

public String getFullName() {
return this.getLastName() + ", " + this.getFirstName();
}

The encapsulation forces you to user getters outside User class. However, it turns out that in this case, I'd better stick to getters instead of "this." accessor anywhere even inside the User class.

Override equals/hashcode in Hibernate domain object

First of all, make sure that you really need to do that. According to this post,
"You only need to implement equals()/hashCode() on your persistent classes if
- it is a used as a composite primary key class
- instances of that class, loaded in different Hibernate Sessions, are in the same Set (or should be compared)"

When you do, be careful as you might run into a tricky problem. If you were me, you would use Eclipse's wizard to create equals/hashcode, which generates code including the below

if (getClass() != other.getClass()) {
return false;
}

The problem is that Hibernate domain objects are proxies, by Javassist for example. This could return false as one is the domain class and the other is the proxy class. A workaround can be found here.

Again, equals/hashcode are very important and don't take a light decision on overriding them. Use this Hibernate page as reference.