Use Regular Expressions in JPA CriteriaBuilder

后端 未结 3 456
南笙
南笙 2021-01-13 06:48

I\'m using the JPA CriteriaBuilder to select entities of type MyEntity from a MySQL db as follows:

String regExp = \"(abc|def)\"
CriteriaBuilder         


        
相关标签:
3条回答
  • 2021-01-13 06:48

    I came across this recently and used the first post to implement the hibernate mysql function option.

    To help save some time for others this is what I did:

    set up the function in your custom dialect file in hibernate:

    public class MySQLDialect extends Dialect {
    
       public MySQLDialect() {
          super();
          ...
          registerFunction("regexp", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "?1 REGEXP ?2"));
          ...
       }
       ...
    }
    

    then within the criteria builder section:

    CriteriaBuilder builder = ...;    
    
    Pattern regexPattern = Pattern.compile("^[0-9]\\|[0-9]+");
    
    Expression<String> patternExpression = builder.<String>literal(regexPattern.pattern());
    
    Path<String> path = ... ;// regex comparison column
    
    // regexp comes from the name of the regex function 
    // defined in the Mysql Dialect file above
    Predicate theRegexPredicate = builder.equal(builder.function("regexp", Integer.class, path, patternExpression), 1);
    

    Then use theRegexPredicate to construct the where clause in your CriteriaBuilder query.

    0 讨论(0)
  • 2021-01-13 06:53

    Pattern matching in JPA queries is limited only to

    • _ - any character
    • % - any string

    REGEXP has operator syntax in MySQL (SELECT 'a' REGEXP 'A') so it cannot be used with CriteriaBuilder.function() API. I'm afraid the best is to run native SQL query.

    If you are using Hibernate you have one more option. You can wrap REGEXP operator in SQLFunctionTemplate, extend hibernate dialect and run with CriteriaBuilder.function().

    0 讨论(0)
  • 2021-01-13 07:08

    Maybe this snippet will help. We had to exclude characters in a search, and we using Oracle. CriteriaBuilder (at least as of 2.1) will let you call a function.

    private static final Pattern UNDESIRABLES = Pattern.compile("[(){},.;!?<>%_-]");
    private static final String UNDESIRABLE_REPLACEMENT = "";
    ...
    

    In the search method, create a Predicate to use in your where clause:

    Expression<String> undesirables = cb.literal(UNDESIRABLES.toString());
    Expression<String> replaceWith = cb.literal(UNDESIRABLE_REPLACEMENT);
    Expression<String> regExp = cb.function("REGEXP_REPLACE", String.class, client.get(Client_.companyName),
        undesirables, replaceWith);
    Predicate companyNameMatch = cb.equal(cb.trim(cb.lower(regExp)), removeUndesireables(name).trim());
    ...
    

    And create a method for the right hand comapare that uses the same values as the left:

    private String removeUndesireables(String name) {
        return UNDESIRABLES.matcher(name).replaceAll(UNDESIRABLE_REPLACEMENT).toLowerCase();
    }
    
    0 讨论(0)
提交回复
热议问题