Search code examples
javahibernatehibernate-criteriajpa-2.1

Is there a way to (locally) bypass or disable an AttributeConverter during a Criteria API call?


Suppose a CreditcardNumb.class with a constructor that checks if the credit-card number is valid.

I then create a CreditcardNumbConverter.class to convert credit-card numbers to Strings in the database:

public class CreditcardnumbConverter
      implements AttributeConverter<CreditcardNumb, String> {

    public String convertToDatabaseColumn(CreditcardNumb cn) {
        if (cn== null) return null;
        return cn.toString();
        }

    public CreditcardNumb convertToEntityAttribute(String cn) {
        if ((cn == null) || cn.trim().isEmpty()) return null;
        return new CreditcardNumb(cn);
        }
    }

This works ok, but now I want to use Hibernate's Criteria API (the new or the old API) to search for credit-card numbers that start with "123":

CreditcardNumb cn = new CreditcardNumb("123");

createCriteria(Wallet.class)
      .add(Restrictions.ilike("creditcard", cn, MatchMode.START))
      .list();

However, since "123" is not a valid credit-card number, the object instantiation fails. Also, this won't even compile, since the ilike method only accepts Strings, not CreditcardNumbs.

My question:

Is there any way to (locally) bypass or disable the conversion, so that I can do something like:

createCriteria(Wallet.class)
      .disable(CreditcardnumbConverter.class))
      .add(Restrictions.ilike("creditcard", "123", MatchMode.START))
      .list();

Or is there any other way to search for credit-card numbers that start with "123" by using the Criteria API (not using HQL).


Solution

  • You could map the credit card column in another property of String type:

    @Entity
    public class Wallet {
    
      private CreditcardNumb creditcard;
    
      @Column(name = ..., insertable = false, updatable = false)
      private String creditcardStr;
    
      ...
    }
    

    The key point is to map this column as being neither insertable nor updatable, so that its value is not persisted (otherwise Hibernate would not know whether to use creditcard or creditcardStr value to update the underlying database column).

    Now your query can look like this:

    createCriteria(Wallet.class)
      .add(Restrictions.ilike("creditcardStr", "123", MatchMode.START))
      .list();