Search code examples
jpaeclipselinkpredicatesoundex

Using Soundex and CriteriaBuilder API from EclipseLink


Currently in the process of creating a object search using CriteriaBuilder, Predicates, JPA 2.0 with EclipseLink as provider.

My challenge is accessing the soundex capabilities and applying it to a dynamically built criteria.

    CriteriaBuilder cb = PersistenceUtil.getEntityManager().getCriteriaBuilder();
    CriteriaQuery<Registration> q = cb.createQuery(Registration.class);
    Root<Registration> dr = q.from(Registration.class);

    List<Predicate> predicates = new ArrayList<Predicate>();

... Loop of my inputs to the query

    predicates.add(cb.equal(dr.get(fieldName),fieldValue));

... and finally

    q.select(dr).where(predicates.toArray(new Predicate[]{}));

    TypedQuery<Registration> query = PersistenceUtil.getEntityManager().createQuery(q).setMaxResults(maxResults);

    List<DeathRegistration> results = query.getResultList();

This obviously works fine for the simple criteria builder items, and I can use 'like', 'greaterThan', date comparison and so on.

I want to enable use of a Expression that uses the EclipseLink soundex() operator. Using EclipseLink provider opens up my ability to create an eclipselink Expression, but I canot figure out how to apply it to a predicate.

                        ReadAllQuery raq = new ReadAllQuery(Registration.class);        
                        ExpressionBuilder eb = raq.getExpressionBuilder();
                        org.eclipse.persistence.expressions.Expression fnExp = ExpressionOperator.soundex().expressionFor(eb.get(fieldName));
                        org.eclipse.persistence.expressions.Expression fnVal = fnExp.equal(fieldValue);

Having a lot of trouble finding documentation that would allow me to create an Expression that can be used in CriteriaBuilder. Is it possible? Can an EclipseLink Expression be converted to a parametrized persistence Expression<>? ... and then be set as a predicate for the built criteria query?


Solution

  • After sleeping on the issue, and some more googling. Here is where I ended up:

        Expression<String> exp = dr.get(fieldName);
        Expression<String> expName = CriteriaBuilderHelper.functionSoundexName(cb, exp);
        Expression<String> expValue = CriteriaBuilderHelper.functionSoundexValue(cb, fieldValue);                               
        predicates.add(cb.equal(expName, expValue));
    

    and my function:

    private static final String SOUNDEX = "soundex";
    /**
    * @param cb the CriteriaBuilder to use
    * @param value the value to soundex
    * @return Expression<String>
    */
    
    public static Expression<String> functionSoundexName(CriteriaBuilder cb, Expression<String> exp) {
        return cb.function(
            SOUNDEX,
            String.class,
            cb.lower(exp)
        );
    }   
    
    public static Expression<String> functionSoundexValue(CriteriaBuilder cb, String value) {
        return cb.function(
            SOUNDEX,
            String.class,
            cb.lower(cb.literal(value))
        );
    }