views:

495

answers:

3

I have a problem with a query using hibernate. The entity class EntityClass has an embedded property embedded of type EmbeddedClass and this property has a nullable property optional. When all properties are set, i can do a very simpel HQL query as:

Query query = getSession().createQuery(
    "FROM EntityClass t WHERE t.embedded = :embedded");
query.setParameter("embedded", embedded);
return (EntityClass) query.uniqueResult();

But when the property optional is null, this does not work, because hibernate creates a SQL query like t.optional=? but =NULL should be IS NULL in SQL. The WHERE clause never matches, the query returns no rows.

Some further reading pointed to Example which is handling null properly. Now my code looks like:

Criteria query = getSession().createCriteria(EntityClass.class);
query.createCriteria("embedded").add(Example.create(embedded));
return (EntityClass) query.uniqueResult();

When running the code I get a ClassCastException:

java.lang.ClassCastException: EmbeddedClass
    at org.hibernate.criterion.Example.getEntityMode(Example.java:279)
    at org.hibernate.criterion.Example.toSqlString(Example.java:209)
    at org.hibernate.loader.criteria.CriteriaQueryTranslator.getWhereCondition(CriteriaQueryTranslator.java:357)
    at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:113)
    at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:82)
    at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:91)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1577)
    at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:306)
    at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:328)

It has something to do with EntityPersister.guessEntityMode() returning null, because hibernate looks for the mapping of the entity class, not the embedded one.

It seems that org.hibernate.criterion.Example can not be used for an embedded class. Any idea how to to this? Is there an ohter approach?

The classes look like:

@Entity
public class EntityClass {
    ...

    @Embedded
    private EmbeddedClass embedded;

    ...
}

@Embeddable
public class EmbeddedClass {
    private String name;
    private String optional;
    ...
}

I use hibernate 3.3.1 and an oracle 10g if that helps.

A: 

Look into the isNull restriction for your criteria. I think it works on a per-session basis:

Criteria entityCriteria = getSession().createCriteria(EntityClass.class);
entityCriteria.add(Restrictions.isNull("optional")); // isNull restriction on the optional attribute of your EntityClass
List results = entityCriteria.list();
Mike Cialowicz
You are right, but this is not the problem. Example creates isNull and eq restrictions.
Arne Burmeister
A: 

Uh, I got it:

After debugging the hibernate code, I discovered you need to build the example on the entity class. So I created an example instance of the entity, set the embedded value and excluded the unused properties on the Example criterion:

Criteria query = getSession().createCriteria(EntityClass.class);
EntityClassexample = new EntityClass();
example.setEmbedded(embedded);
query.add(Example.create(example).excludeNone()
    .excludeProperty("id").excludeProperty("other"));
return (EntityClass) query.uniqueResult();
Arne Burmeister
A: 

That worked fine for me ! I had to use excludeZeroes()

Thank you Fernando.

Fernando