📜 ⬆️ ⬇️

User criteria in Hibernate

In the previous article, I explained how to teach Hibernate to store user-defined data types. Now let's try to use this data when filtering samples. Let's declare the result we want to get:
  1. String filteringTag = "habr" ; Session session = ... ; Criteria criteria = session. createCriteria ( StringArrayContainer. class ) ; criteria. add ( new StringArrayContainsCriterion ( "tags" , filteringTag ) ) ; List containers = criteria. list ( ) ; // , "habr" ...
  2. String filteringTag = "habr" ; Session session = ... ; Criteria criteria = session. createCriteria ( StringArrayContainer. class ) ; criteria. add ( new StringArrayContainsCriterion ( "tags" , filteringTag ) ) ; List containers = criteria. list ( ) ; // , "habr" ...
  3. String filteringTag = "habr" ; Session session = ... ; Criteria criteria = session. createCriteria ( StringArrayContainer. class ) ; criteria. add ( new StringArrayContainsCriterion ( "tags" , filteringTag ) ) ; List containers = criteria. list ( ) ; // , "habr" ...
  4. String filteringTag = "habr" ; Session session = ... ; Criteria criteria = session. createCriteria ( StringArrayContainer. class ) ; criteria. add ( new StringArrayContainsCriterion ( "tags" , filteringTag ) ) ; List containers = criteria. list ( ) ; // , "habr" ...
  5. String filteringTag = "habr" ; Session session = ... ; Criteria criteria = session. createCriteria ( StringArrayContainer. class ) ; criteria. add ( new StringArrayContainsCriterion ( "tags" , filteringTag ) ) ; List containers = criteria. list ( ) ; // , "habr" ...
  6. String filteringTag = "habr" ; Session session = ... ; Criteria criteria = session. createCriteria ( StringArrayContainer. class ) ; criteria. add ( new StringArrayContainsCriterion ( "tags" , filteringTag ) ) ; List containers = criteria. list ( ) ; // , "habr" ...


First, we write a universal implementation of the search criteria. To do this, we will make a small change to the StringArrayCustomType.nullSafeGet and StringArrayCustomType.nullSafeSet methods, in particular we will surround the value stored in the column with spaces. (Changes in lines 7 and 25)
  1. @Override
  2. public Object nullSafeGet ( ResultSet rs, String [ ] names, Object owner ) throws HibernateException, SQLException {
  3. String value = ( String ) Hibernate. TEXT . nullSafeGet ( rs, names [ 0 ] ) ;
  4. if ( value == null ) {
  5. return null ;
  6. } else {
  7. String [ ] array = StringUtils. split ( value. trim ( ) , '' ) ;
  8. for ( int i = 0 ; i < array. length ; i ++ ) {
  9. array [ i ] = WhitespaceEscapeUtil. unescape ( array [ i ] ) ;
  10. }
  11. return array ;
  12. }
  13. }
  14. @Override
  15. public void nullSafeSet ( PreparedStatement st, Object value, int index ) throws HibernateException, SQLException {
  16. if ( value == null ) {
  17. Hibernate. TEXT . nullSafeSet ( st, null , index ) ;
  18. } else {
  19. String [ ] array = ( String [ ] ) value ;
  20. String [ ] copy = new String [ array. length ] ;
  21. for ( int i = 0 ; i < array. length ; i ++ ) {
  22. copy [ i ] = WhitespaceEscapeUtil. escape ( array [ i ] ) ;
  23. }
  24. Hibernate. TEXT . nullSafeSet ( st, '' + StringUtils. join ( copy, '' ) + '' , index ) ;
  25. }
  26. }

Now neatly implement the org.hibernate.criterion.Criterion interface.
  1. public class GenericStringArrayContainsCriterion extends LikeExpression {
  2. public GenericStringArrayContainsCriterion ( String propertyName, String value ) {
  3. super ( propertyName, "%" + WhitespaceEscapeUtil. escape ( value ) + "%" )
  4. }
  5. }
It is clear that the implementation through like is not very efficient in terms of performance. In order to optimize, we will write the same thing, using the capabilities of PostgreSQL 8.x.
  1. public class PostgresStringArrayContainsCriterion implements Criterion {
  2. private final String propertyName ;
  3. private final String value ;
  4. private final String TEMPLATE = "to_tsvector ('simple', {column}) @@ plainto_tsquery ('simple',?)" ;
  5. private static final char TAG_SEPARATOR = '' ;
  6. public PostgresStringArrayContainsCriterion ( String propertyName, String value ) {
  7. this . propertyName = propertyName ;
  8. this . value = WhitespaceEscapeUtil. escape ( value ) ;
  9. }
  10. public String toSqlString ( Criteria criteria, CriteriaQuery criteriaQuery ) throws HibernateException {
  11. return StringHelper. replace ( TEMPLATE, "{column}" , criteriaQuery. getColumn ( criteria, propertyName ) ) ;
  12. }
  13. public TypedValue [ ] getTypedValues ( Criteria criteria, CriteriaQuery criteriaQuery ) throws HibernateException {
  14. return new TypedValue [ ] { new TypedValue ( Hibernate. STRING , value, EntityMode. POJO ) } ;
  15. }
  16. }
And using the “strategy” template, we will choose the implementation depending on the current dialect:
  1. public class StringArrayContainsCriterion implements Criterion {
  2. private final String propertyName ;
  3. private final String value ;
  4. public StringArrayContainsCriterion ( String propertyName, String value ) {
  5. this . propertyName = propertyName ;
  6. this . value = value ;
  7. }
  8. public String toSqlString ( Criteria criteria, CriteriaQuery criteriaQuery ) throws HibernateException {
  9. return getStrategy ( criteriaQuery. getFactory ( ) . getDialect ( ) ) . toSqlString ( criteria, criteriaQuery ) ;
  10. }
  11. public TypedValue [ ] getTypedValues ( Criteria criteria, CriteriaQuery criteriaQuery ) throws HibernateException {
  12. return getStrategy ( criteriaQuery. getFactory ( ) . getDialect ( ) ) . getTypedValues ( criteria, criteriaQuery ) ;
  13. }
  14. public Criterion getStrategy ( Dialect dialect ) {
  15. if ( dialect instanceof PostgreSQLDialect ) {
  16. return new PostgresStringArrayContainsCriterion ( propertyName, value ) ;
  17. } else {
  18. return new GenericStringArrayContainsCriterion ( propertyName, value ) ;
  19. }
  20. }
  21. }


Well, that's all. Now we can save custom types and filter by them.

______________________
The text was prepared in the Blog Editor from © SoftCoder.ru

')

Source: https://habr.com/ru/post/91434/


All Articles