Introduktion till Criteria API
Det finns två sätt att skriva databasfrågor i Hibernate:
- Viloläge frågespråk
- Kriterier API
Du har redan träffat den första för länge sedan, det är dags att bekanta dig med Criteria API. Detta är ett mycket kraftfullt verktyg, någon gång var det ännu mer populärt än HQL. Nu är det inte så populärt längre, men för vissa uppgifter kommer det definitivt att vara en bättre lösning än HQL.
I vilket fall som helst kan du inte lära dig Hibernate utan att bekanta dig med Criteria API. Låt oss skriva ett litet exempel, och sedan analyserar vi det. Till exempel kommer vi att begära alla anställda (Anställd) från databasen. Här är vad vi får:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Employee> critQuery = builder.createQuery(Employee.class);
Root<Employee> root = critQuery.from(Employee.class);
critQuery.select(root);
Query<Employee> query = session.createQuery(critQuery);
List<Employee> results = query.getResultList();
Ser komplicerat ut. Låt oss skriva samma HQL-fråga för jämförelse:
String hqlQuery = "from Employee";
Query<Employee> query = session.createQuery(hqlQuery);
List<Employee> results = query.getResultList();
Observera att de två sista raderna i båda exemplen är nästan identiska: vi skapar ett frågeobjekt och använder det för att få en lista. Detta antyder att resten av raderna gör något identiskt.
Titta på rad 3 och 4 i det första exemplet:
Root<Employee> root = critQuery.from(Employee.class);
critQuery.select(root);
Låt oss skriva dem på en rad:
critQuery.select(critQuery.from(Employee.class));
Påminner det dig inte om något? Och om du färgar det lite annorlunda:
critQuery.select(critQuery.from(Employee.class));
Ja, det här är en så knepig konstruktion av SELECT FROM-frågan.
Exempel på att arbeta med Criteria API
För en bättre förståelse ska jag bara ge några exempel.
Begäran 1 . Få alla anställda med en lön över 10 tusen:
critQuery.select(critQuery.from(Employee.class)).where(builder.gt(root.get("salary"), 10000));
Begäran 2 . Få alla anställda med en lön på mindre än 50 tusen:
critQuery.select(critQuery.from(Employee.class)).where(builder.lt(root.get("salary"), 50000));
Begäran 3 . Få alla anställda vars jobbtitel innehåller ordet "test":
critQuery.select(critQuery.from(Employee.class)).where(builder.like(root.get("occupation"), "%test%"));
Begäran 4 . Få alla anställda med en lön på 10 till 50 tusen:
critQuery.select(critQuery.from(Employee.class)).where(builder.between(root.get("salary"), 10000, 50000));
Begäran 5 . Få alla anställda vars namn är null:
critQuery.select(critQuery.from(Employee.class)).where(builder.isNull(root.get("name")));
Begäran 6 . Få alla anställda vars namn inte är null:
critQuery.select(critQuery.from(Employee.class)).where(builder.isNotNull(root.get("name")));
Det är bara ett så knepigt sätt att konstruera en fråga:
- Först får du föremåletCriteriaBuilder.
- Använd den sedan för att skapa ett objektCriteriaQuery.
- Sedan börjar du lägga till delar till den medCriteriaQueryOchCriteriaBuilder.
Så här kan du ställa in parametrar för:
- VÄLJ
- FRÅN
- VAR
Använder ocksåCriteriaBuilderdu kan konstruera olika förutsättningar för VAR.
Avancerat arbete med Criteria API
Med hjälp av Criteria API kan du skapa en fråga av vilken komplexitet som helst. Och det här är fantastiska nyheter. Till exempel vill du ha en komplex WHERE-sats. Så här gör du:
Predicate greaterThan = builder.gt(root.get("salary"), 1000);
Predicate testers = builder.like(root.get("occupation"), "test%");
critQuery.select(critQuery.from(Employee.class)).where(builder.or(greaterThan, testers));
Om du vill skriva AND istället för ELLER behöver du bara ändra den sista raden:
critQuery.select(critQuery.from(Employee.class)).where(builder.and(greaterThan, testers));
Allt är faktiskt väldigt enkelt. Låt mig ge dig en tabell med några jämförelser:
SQL | Metod | Fullständigt rekord |
---|---|---|
a<b | lt(a, b) | builder.lt(a, b) |
a > b | gt(a, b) | builder.gt(a, b) |
a ELLER b | eller(a,b) | byggare.eller(a, b) |
a OCH b | och (a,b) | byggare.och(a,b) |
a GILLA b | som (a,b) | builder.like(a, b) |
a MELLAN (c, d) | mellan (a, c, d) | builder.between(a, c, d) |
a ÄR NULL | ärNull(a) | builder.isNull(a) |
a ÄR INTE NULL | isNotNull(a) | builder.isNotNull(a) |
Allt är enkelt, eller hur?
Och hur lägger vi till sortering i frågan? Väldigt enkelt:
critQuery.select( critQuery.from(Employee.class) );
critQuery.where( builder.and(greaterThan, testers) );
critQuery.orderBy( builder.asc(root.get("salary"), builder.desc(root.get("joinDate") )
Du ringer bara på objektetCriteriaQueryorderBy() -metoden och skicka de nödvändiga parametrarna till den.
Så här skulle samma fråga se ut i HQL. Jämföra:
select * from Employee
where (…) and (…)
order by 'salary' asc, 'joinDate' desc
Du behöver bara komma ihåg 3 saker:
- Nyckeloperatorer som SELECT, FROM, WHERE anropas på ett objektCriteriaQuery.
- Hjälpoperatorer som AND, OR, DESC anropas på objektetCriteriaBuilder.
- Fältnamn tas från objektet via get()rot.