How to query by embedded example containing null values using hibernate?
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.
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);
EntityClass example = new EntityClass();
example.setEmbedded(embedded);
query.add(Example.create(example).excludeNone()
.excludeProperty("id").excludeProperty("other"));
return (EntityClass) query.uniqueResult();
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();
精彩评论