Статьи

Собственные функции SQL Hibernate в хранилище данных Spring

JPA предоставляет @NamedNativeQuery для использования собственного SQL. Однако использование не очень удобно, особенно когда вам нужно отобразить несколько объектов в вашем родном SQL. Вы должны определить набор отображений SqlResultSetMapping, который довольно подвержен ошибкам.

Для тех, кто ранее использовал функции Hibernate Native SQL, вы обнаружите, что его гораздо проще использовать, чем @NamedNativeQuery от JPA. В последних проектах я использую Spring Data JPA. Я добавил функции собственных запросов гибернации в свой репозиторий базы данных Spring. Теперь вы можете выполнить собственный запрос в JPA без SqlResultSetMapping.

1. Добавьте свои аннотации @NativeQueries и @NativeQuery.

1
2
3
4
5
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQueries {
 NativeQuery[] queries() default  {};
}
1
2
3
4
5
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQuery {
 String name()  default "";
 String sql()  default "";
}

2. Добавьте метод «queryNatively» в базовый репозиторий данных Spring.

Если вы не знаете, как добавить пользовательское поведение в базовый репозиторий JPA данных Spring, см. Мой предыдущий пост о том, как подробно настроить базовый репозиторий JPA данных Spring . В предыдущем посте вы можете видеть, что я намеренно предоставляю интерфейс репозитория (то есть свойство springDataRepositoryInterface) в GenericRepositoryImpl. Эти маленькие хитрости позволяют мне легко получить доступ к аннотации в интерфейсе репозитория.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public List queryNatively(String nativeQueryName, LinkedHashMap<String,Class<?>> inEntityClasses, Map inParams ){
 SQLQuery query =  this.createHibernateNativeQuery( nativeQueryName,  inParams );
     //add entities
     if (inEntityClasses!=null) {     
      for (Object key: inEntityClasses.keySet()) {
    String entityClassAlias = key.toString();
    Class<?> entityClass = (Class<?>)inEntityClasses.get(key); 
    query.addEntity(entityClassAlias,entityClass);
         }   
     }
              
     //add parameter
     if (inParams != null){
      for (Object key: inParams.keySet()) {
    String queryParamName = key.toString();
    Object queryParamValue = inParams.get(key);
    query.setParameter(queryParamName, queryParamValue);
         }
     
     return (query!=null)? query.list() : null ;
  }
     
 
  private SQLQuery createHibernateNativeQuery (String nativeQueryName, Map inParams ){
     if (GenericRepository.class.isAssignableFrom(getSpringDataRepositoryInterface())) {
       
      Annotation nativeQueryAnn = getSpringDataRepositoryInterface().getAnnotation(NativeQueries.class);
      if(nativeQueryAnn != null){
       NativeQueries nativeQueries = (NativeQueries)nativeQueryAnn;
       NativeQuery[] queries  = nativeQueries.queries();
    for (NativeQuery sqlquery : queries) {
           
     if (StringUtils.equals(nativeQueryName, sqlquery.name())) {
      String sql  = sqlquery.sql();
       
      Session hiernateSess = em.unwrap(Session.class);
         SQLQuery query = hiernateSess.createSQLQuery(sql);
          
         //add parameter
         if (inParams != null){
          for (Object key: inParams.keySet()) {
        String queryParamName = key.toString();
        Object queryParamValue = inParams.get(key);
        query.setParameter(queryParamName, queryParamValue);
             }
         
          
         return query;
     }   
    }
      }
      
     }
     return null;
  }

3. Пример использования

В своем интерфейсе репозитория определите, какие собственные запросы SQL вы хотите использовать, используя аннотации @NativeQueries и @NativeQuery. Использование аналогично вызову спящих функций собственных запросов. Вы можете просто увидеть псевдоним гибернации и ссылки на свойства .

01
02
03
04
05
06
07
08
09
10
@NativeQueries (
 queries = {
   @NativeQuery(name="query1",
         sql="SELECT {cat.*}, {mother.*}  FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID and c.name =  :catName "),
   @NativeQuery(name="query2",
         sql="SELECT {cat.*} FROM CATS where c.ID =  :catName")      
 }
)
public interface CatRepository extends GenericRepository<Cat, Long> {
}

В вашем сервисе или бизнес-классе, который внедряет ваш репозиторий, вы можете просто вызвать метод queryNatively () для выполнения собственного запроса SQL.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Service
public class CatService {
  
 @Inject
 private CatRepository catRepository;
  
 public List<Cat> searchCat( String catName) {
     
  List<Cat> catList;
  
  // Add entity mapping for your query
  HashMap<String, Object> inParams = new HashMap<String, Object>();
  inParams.put("catName", "Felix");
   
   
  // Prepare parameters for your native sql
  LinkedHashMap<String, Object> entityMap = new LinkedHashMap<String, Object>();
  entityMap.put("cat", Cat.class);
  entityMap.put("mother",Mother.class);
  
 
  
  catList = catRepository.queryNatively(
    "query1", "",entityParam);
  
  return catList;
 }
}

Ссылка: Добавление собственных функций Hibernate SQL в ваш репозиторий Spring от нашего партнера по JCG Бориса Лама в блоге Programming Peaceful .