Transform SimpleExpresion/LogicalExpression in JPA

Hi,

I have legacy code and a method that looks like this:

public List<ENTITY> findByCriteria(final Map<String, Object> criteriaMap, final List<String> fields, final Class<ENTITY> entityClass) {

	final Criteria criteria = this.getSession().createCriteria(entityClass);
	final Set<String> keys = criteriaMap.keySet();

	Object object;
	CriteriaValue criteriaValue;
	CriteriaValue.Operator operator;

	for (String key:keys) {
		object = criteriaMap.get(key);

		if (object instanceof SimpleExpression) {
			criteria.add((SimpleExpression)object);
		} else if (object instanceof LogicalExpression) {
			criteria.add((LogicalExpression)object);
		} else if (object instanceof Criterion) {
			criteria.add((Criterion)object);
		} else if (!isDefaultCriteria(key)) {
		...
	}
...
}

Is there a way to transform the if-clauses to JPA CriteriaBuilder? Or more specific, hat’s the equivalent of SimpleExpression/LogicalExpression in JPA?

What I would do is to try to transform the SimpleExpression into a Predicate like this:

protected SimpleExpression(String propertyName, Object value, String op) {
	this.propertyName = propertyName;
	this.value = value;
	this.op = op;

	protected final String getOp() {
		return op;
	}

	public String getPropertyName() {
		return propertyName;
	}

	public Object getValue() {
		return value;
	}
}
public Predicate simpleExpressionToPredicateTransformer(SimpleExpression simpleExpression)
	switch (simpleExpression.getOp()) {
		case EQ:
			// create and return predicate
		case iLIKE:
			// create and return predicate
		case LIKE:
			// create and return predicate
		case LE:
			// create and return predicate
	}
}

But unfortunately, the .getOp() method in SimpleExpression is protected and I cannot access it.

Just for completeness, here’s the CriteriaValue class

public class CriteriaValue implements Serializable {
		
	private static final long serialVersionUID = -5305816199528069626L;
	
	public enum Type {    	    			
		TEXT, 
		NUMBER,
		DATE 
	}
	
	/**
	 * The Enum Operator.
	 */
	public enum Operator {
    		    
	    EQ, 
		iLIKE, 
		LIKE, 
		LE, 
		GE, 
		LT, 
		GT,
		OR,
		AND
		IN,				
		NE,
	}
		
	private Object value;	
	
	private Type type;	
	
	private Operator operator;
	
	private String key;
	
	// Getters and setters omitted
}

You should avoid using the legacy Hibernate Criteria API as it was removed in Hibernate 6 and is deprecated for a while now. With your custom expression/criteria objects, you can do whatever you want and create appropriate JPA Criteria objects by using CriteriaBuilder.

Hi Beikov,

thanks for your reply. I’m migrating an existing Hibernate 3 app to version 5 and the usage of criteria api unfortunately took place years ago and needs to be migrated now. Could you please elaborate on what that means?

With your custom expression/criteria objects, you can do whatever you want and create appropriate JPA Criteria objects by using CriteriaBuilder.

I’m trying to write a transformer method from Hibernates legacy Criteria API to CriteriaBuilder but I don’t know how to extract the required information from a Criteria.

The SimpleExpression and Logical Expressions are not a problem anymore, as they were only used on 2 occasions. I did migrate these occasions to CriteriaBuilder. Butt the legacy Criterias are used throughout our app and rewriting the occurrences seems not to be feasible at the moment. That’s why I would like to write some kind of interceptor that transforms the Criteria to CriteriaQuery.

There are many tutorials on the internet that explain how the JPA Criteria API works:

You can copy the classes(LogicalExpression, etc.) from Hibernate that you use in your app, and then do a refactoring in your source tree to rename/move to your own package. Now you have classes that you can simply change and expose the getOp method, which you can then use to implement the transformation.

Ah ok, got it. Thank you!