Hibernate version: 2.1.6
Hi, all,
Briefly, I map a property of a persistent class by a UserType to two columns and try to use the property in the where-clause of a HQL query. When I query by the Query API, it fails with a QueryException complaining "path expression ends in a composite value". But by the Criteria API it works well. Is this the normal case?
In details, I have a persistent class eg.WebPage with a "url" property, and the instance of WebPage is offten looked up by its url property:
HQL: from eg.WebPage page where page.url = :url
But since the url is too long to allow for creating an index on the underlying table column, the query above performs poorly.
So I tried to add a column which stores the url's hashcode and to create an index on it. On the other hand, I don't like to pollute the WebPage class by adding a property "hashcode". And that's why I tried UserType.
By the user type eg.UrlUserType the property "url" is mapped to two columns "url" and "hashcode", hoping that "hashcode" will come into the where-clause of resulting SQL together with the "url", which in turn makes use of the index on the "hashcode" column.
But when I used Query with the above HQL and bind the parameter by:
query.setParameter("url", someUrlInString,
Hibernate.custom(UrlUserType));
executing the query by Query.list() gave a QueryException complaining "path expression ends in a composite value". I don't know whether it was normal, but when I tried the Criteria API, it worked well:
Criteria c = ses.createCriteria(WebPage.class);
c.add(Expression.eq("url", urlInString));
c.list();
The following are some fragments of my mapping document and the user type implementation. Hope they are detailed enough.
In the mapping document of WebPage, I mapped the property "url" this way:
<property name="url"
type="eg.UrlUserType" >
<column name="url" />
<column name="hashcode"/>
</property>
And the nullSafeGet(..) and nullSafeSet(..):
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws HibernateException, SQLException {
if(rs.wasNull()) {
return null;
}
return rs.getString(names[0]);
}
public void nullSafeSet(PreparedStatement pstmt, Object value, int idx)
throws HibernateException, SQLException {
if(value == null) {
pstmt.setNull(idx, Types.VARCHAR);
pstmt.setNull(idx+1, Types.INTEGER);
}
else {
String url = (String) value;
pstmt.setString(idx, url);
pstmt.setInt(idx+1, url.hashCode());
}
}
|