Heim  >  Artikel  >  Java  >  Detaillierte Erläuterung des dynamischen Abfragecodes in JAVA Spring Data JPA

Detaillierte Erläuterung des dynamischen Abfragecodes in JAVA Spring Data JPA

Y2J
Y2JOriginal
2017-04-25 16:42:562400Durchsuche

spring Data JPA vereinfacht die Entwicklung unserer Persistenzschicht erheblich, aber in tatsächlichen Anwendungen benötigen wir immer noch dynamische Abfragen.

Wenn das Front-End beispielsweise über mehrere Bedingungen verfügt, von denen viele optional sind, sollte das Back-End-SQL anpassbar sein. Wenn Sie den Ruhezustand verwenden, können Sie die verwendeten Bedingungen beurteilen Natürlich vereinfacht Spring Data JPA nicht nur unsere Entwicklung, sondern bietet auch Unterstützung.

Durch die Implementierung der durch Kriterium 2 implementierten dynamischen Abfrage muss unsere Repo-Schnittstelle die JpaSpecificationExecutor-Schnittstelle erben, bei der es sich um eine generische Schnittstelle handelt.

Übergeben Sie dann bei der Abfrage einfach dynamische Abfrageparameter, Paging-Parameter usw.

Es ist sehr einfach zu verwenden, aber um zu verstehen, warum, stellen wir zunächst die Kriterien-API vor.

Kriterien-API

Eine Abfrage ist für Java-Objekte typsicher, wenn der Compiler Syntax-Korrektheitsprüfungen für die Abfrage durchführen kann. Version 2.0 der Java™ Persistence API (JPA) führt die Criteria API ein, die erstmals typsichere Abfragen in Java-Anwendungen bringt und einen Mechanismus zum dynamischen Erstellen von Abfragen zur Laufzeit bereitstellt. In diesem Artikel wird beschrieben, wie Sie dynamische, typsichere Abfragen mithilfe der Criteria-API und der eng verwandten Metamodel-API schreiben.

Wenn wir Spring Data JPA verwenden, können wir, solange unsere Repo-Ebene die JpaSpecificationExecutor-Schnittstelle erbt, zunächst die Spezifikation für dynamische Abfragen verwenden:

public interface JpaSpecificationExecutor<T> { 
 T findOne(Specification<T> spec); 
 List<T> findAll(Specification<T> spec); 
 Page<T> findAll(Specification<T> spec, Pageable pageable); 
 List<T> findAll(Specification<T> spec, Sort sort); 
 long count(Specification<T> spec); 
}

Sie können sehen, dass 5 Methoden bereitgestellt werden und die Parameter und Rückgabewerte der Methoden ihre Absichten klar zum Ausdruck bringen. Unter den Parametern sollten Pageable und Sort relativ einfach sein, sie sind Paging-Parameter bzw. Sortierparameter, und der Schwerpunkt liegt auf dem Spezifikationsparameter. Schauen wir uns zunächst die Definition dieser Schnittstelle an:

public interface Specification<T> { 
 Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb); 
}

Einer von Die Methodenrückgabe ist die Datenstruktur der dynamischen Abfrage.


javax.persistence.criteria.Predicate toPredicate(javax.persistence.criteria.Root<T> root,
javax.persistence.criteria.CriteriaQuery<?> query,
javax.persistence.criteria.CriteriaBuilder cb);

Die hier verwendeten Spezifikationen sind alle Spezifikationen in Java EE. Für die konkrete Implementierung verwende ich natürlich auch andere diejenigen, die das Data-Persistenz-Layer-Framework implementieren.
Hier müssen wir zurückgehen und uns einige Dinge in der Kriterien-API ansehen:

Kriterienabfragen basieren auf dem Konzept des Metamodells, bei dem es sich um eine verwaltete Entität für eine bestimmte Persistenzeinheit handelt. Diese Entitäten können Entitätsklassen, eingebettete Klassen oder zugeordnete übergeordnete Klassen sein.

CriteriaQuery-Schnittstelle: Stellt ein bestimmtes Abfrageobjekt der obersten Ebene dar, das verschiedene Teile der Abfrage enthält, z. B.: Auswählen, Von, Wo, Gruppieren nach, Sortieren nach usw. Hinweis: CriteriaQuery-Objekte Funktioniert nur mit Entitätstypen. Oder der eingebettete Typ der Kriterienabfrage funktioniert.

Root-Schnittstelle: stellt das Stammobjekt der Kriterienabfrage dar. Der Abfragestamm der Kriterienabfrage definiert den Entitätstyp und kann die gewünschten Ergebnisse erhalten für die zukünftige Navigation. Die FROM-Klausel in einer SQL-Abfrage ähnelt

1: Stamminstanzen werden typisiert und definieren die Typen, die in der FROM-Klausel der Abfrage erscheinen können.

2: Die Abfragestamminstanz kann durch Übergabe eines Entitätstyps an die Methode AbstractQuery.from abgerufen werden.

3: Kriterienabfrage, die mehrere Abfragewurzeln haben kann.

4: AbstractQuery ist die übergeordnete Klasse der CriteriaQuery-Schnittstelle, die Methoden zum Abrufen des Abfragestamms bereitstellt. CriteriaBuilder-Schnittstelle: das Builder-Objekt, das zum Erstellen von CritiaQuery verwendet wird. Prädikat: ein einfacher oder komplexer Prädikattyp, der tatsächlich einer Bedingung oder einer Kombination von Bedingungen entspricht

Die unterstützten Methoden sind sehr leistungsfähig, wie unten angegeben Sie können sich auf ein Beispiel beziehen. Ebenso können Sie komplexere Abfragen basierend auf dem Beispiel schreiben:

Repo-Schnittstelle:

public interface DevHREmpConstrastDao 
 extends JpaRepository<DevHREmpConstrast, Long>,JpaSpecificationExecutor<DevHREmpConstrast>

Abfragebeispiel 1:

/** 
 * 条件查询时动态组装条件 
 */ 
private Specification<DevHREmpConstrast> where( 
  final String corg,final String name,final String type,final String date,final String checker){ 
 return new Specification<DevHREmpConstrast>() { 
  @Override 
  public Predicate toPredicate(Root<DevHREmpConstrast> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
   List<Predicate> predicates = new ArrayList<Predicate>(); 
   //机构 
   if(corg!=null&&!corg.equals("")){ 
    List<String> orgIds = organizationDao.findByName("%"+corg+"%"); 
    if(orgIds.size()>0&&orgIds.size()<1000) 
     predicates.add(root.<String>get("confirmOrgNo").in(orgIds));//confirmOrgNo 
   } 
   //名字 
   if(name!=null&&!name.equals("")){ 
    List<String> userIds = userDao.findByName(name); 
    if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 
     predicates.add(root.<String>get("hrUserName").in(userIds)); 
   } 
   //类型 
   if(type!=null&&!type.equals("")) 
    predicates.add(cb.equal(root.<String>get("hrUpdateType"),type)); 
   //日期 
   if(date!=null&&!date.equals("")){ 
    //处理时间 
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
    Date startDate; 
    Date endDate; 
    try { 
     startDate = format.parse(date); 
    } catch (ParseException e) { 
     startDate = new Date(946656000000L);//2000 01 01 
    } 
    endDate = startDate; 
    Calendar calendar = Calendar.getInstance() ; 
    calendar.setTime(endDate); 
    calendar.add(Calendar.DATE, 1); 
    endDate = calendar.getTime(); 
    calendar = null; 
    predicates.add(cb.between(root.<Date>get("insDate"),startDate,endDate)); 
   } 
   //审核人 
   if(checker!=null&&!checker.equals("")){ 
    List<String> userIds = userDao.findByName(checker); 
    if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 
     predicates.add(root.<String>get("confirmUserId").in(userIds)); 
   } 
   return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); 
  } 
 }; 
}

Abfragebeispiel 2:

/** 
 * 条件查询时动态组装条件 
 */ 
 private Specification<DevHREmpConstrast> where( 
   final String corg,final String name,final String type,final String date,final String checker){ 
  return new Specification<DevHREmpConstrast>() { 
   @Override 
   public Predicate toPredicate(Root<DevHREmpConstrast> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
    List<Predicate> predicates = new ArrayList<Predicate>(); 
    //机构 
    if(corg!=null&&!corg.equals("")){ 
     List<String> orgIds = organizationDao.findByName("%"+corg+"%"); 
     if(orgIds.size()>0&&orgIds.size()<1000) 
      predicates.add(root.<String>get("confirmOrgNo").in(orgIds));//confirmOrgNo 
    } 
    //名字 
    if(name!=null&&!name.equals("")){ 
     List<String> userIds = userDao.findByName(name); 
     if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 
      predicates.add(root.<String>get("hrUserName").in(userIds)); 
    } 
    //类型 
    if(type!=null&&!type.equals("")) 
     predicates.add(cb.equal(root.<String>get("hrUpdateType"),type)); 
    //日期 
    if(date!=null&&!date.equals("")){ 
     //处理时间 
     SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
     Date startDate; 
     Date endDate; 
     try { 
      startDate = format.parse(date); 
     } catch (ParseException e) { 
      startDate = new Date(946656000000L);//2000 01 01 
     } 
     endDate = startDate; 
     Calendar calendar = Calendar.getInstance() ; 
     calendar.setTime(endDate); 
     calendar.add(Calendar.DATE, 1); 
     endDate = calendar.getTime(); 
     calendar = null; 
     predicates.add(cb.between(root.<Date>get("insDate"),startDate,endDate)); 
    } 
    //审核人 
    if(checker!=null&&!checker.equals("")){ 
     List<String> userIds = userDao.findByName(checker); 
     if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 
      predicates.add(root.<String>get("confirmUserId").in(userIds)); 
    } 
    return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); 
   } 
  }; 
 }

Rufen Sie dann die Dao-Layer-Methode auf und übergeben Sie die von der where()-Methode zurückgegebenen Parameter.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des dynamischen Abfragecodes in JAVA Spring Data JPA. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn