We have seen Hibernate's set of Restrictions and they cover a very large range of queries. However Hibernate also allows the creation of a custom Criterion that can be used in the criteria.
I created a simple Criterion class that is used to check the length of string properties.
I created a simple Criterion class that is used to check the length of string properties.
@SuppressWarnings("serial") public class LengthExpression implements Criterion { private final String propertyName; private final int value; public LengthExpression(final String propertyName, final int value) { this.propertyName = propertyName; this.value = value; } @Override public String toSqlString(final Criteria criteria, final CriteriaQuery criteriaQuery) throws HibernateException { criteriaQuery.getFactory().getDialect(); final String[] columns = criteriaQuery.getColumnsUsingProjection( criteria, this.propertyName); final String queryFragment = "length(" + columns[0] + ") = ?"; return queryFragment; } @Override public TypedValue[] getTypedValues(final Criteria criteria, final CriteriaQuery criteriaQuery) throws HibernateException { // An ordered pair of a value and its Hibernate type return new TypedValue[] { new TypedValue(Hibernate.INTEGER, Integer.valueOf(value), EntityMode.POJO) }; } }In the above code:
- The class implements the Criterion Interface which exposes two methods.
- The toSqlString() method is what generates the actual sql fragment. As we work with prepared statements, "?" ares used. In this case the sql length function is used. The alias used for property in the actual query is obtained using the getColumnsUsingProjection() method.
- The getTypedValues() method tells Hibernate about the data Type to be used in the query. In this case the parameter will be set using the preparedStatement.setInt() method.
public static void testCustomCriterion() { final Session session = sessionFactory.openSession(); Criteria criteria = session.createCriteria(Entity.class); criteria.add(new LengthExpression("name", 7)); List<Entity> entities = criteria.list(); System.out.println(entities); }The result of the execution is below:
3484 [main] DEBUG org.hibernate.SQL - /* criteria query */ select this_.ID as ID0_0_, this_.NAME as NAME0_0_, this_.DATE as DATE0_0_, this_.MASTER_ID as MASTER4_0_0_ from ENTITY this_ where length(this_.NAME) = ? ... 3484 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - preparing statement 3516 [main] DEBUG org.hibernate.type.IntegerType - binding '7' to parameter: 1 ... 3625 [main] DEBUG org.hibernate.connection.DriverManagerConnectionProvider - re turning connection to pool, pool size: 1 [[Entity] : ( id 2 , data : entity1 , master.Id : 1 , date : null )], [Entity] : ( id 3 , data : entity2 , master.Id : 1 , date : null )]]As can be seen the query generated includes the length() function. Also the parameter(7) was bound to the prepared statement.
very well explained!!!
ReplyDeleteThanks