Tuesday, January 29, 2008

<rage>Hibernate !!!</rage>

So, this is the first post of the new year, and regrettably, it's one written in anger over Hibernate ... again.

This time, it's regarding the Criteria API. It seems that if you want to be able to use the Criteria API for querying entities with composite properties (or ids), you have to use a special notation. Say you have the following entities :


public class Cat implements java.io.Serializable {
@Embedded
private CatMetadata metadata;

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

//constructors, getters, setters, etc omitted for clarity
}

@Embeddable
public class CatMetadata implements java.io.Serializable {

@Column(name = "name")
private String name;

@Column(name = "age")
private int age;

@Column(name = "colour")
private int colour;

//constructors, getters, setters, etc omitted for clarity
}


If you wanted to get all cats with the name "Spunky", your first instinct would likely be to do something like this (given what's in the Hibernate documentation):

Session s = sessionFactory.openSession();
List cats = s.createCriteria(Cat.class)
.createCriteria("metadata")
.add(Restrictions.eq("name","Spunky"))
.list();

s.close();

for(Cat c : cats) {
System.out.println(c);
}


...and your first instinct would be quite wrong. The above code would work just fine if
CatMetadata
were an assocation rather than embedded. Instead, if
CatMetadata
is embedded, you must do the following :


List cats = s.createCriteria(Cat.class)
.add(Restrictions.eq("metadata.name","Spunky"))
.list();



Note the difference in the restriction that's added to the criteria. The desired end property must be expressed in dotted notation relative to the embedded object. This little inconsistency tripped me up for hours trying to Google a fix for it. Why Hibernate couldn't just stick with a consistent scheme for dealing with nested properties is beyond me (and given time constraints at work, I really don't have the time to go figure it out).

No comments: