JPA-criteria

1. Overzicht

In deze zelfstudie bespreken we een zeer nuttige JPA-functie: criteriaquery's.

Het stelt ons niet alleen in staat om queries te schrijven zonder ruwe SQL uit te voeren, maar geeft ons ook wat objectgeoriënteerde controle over de queries, wat een van de belangrijkste features van Hibernate is. De Criteria API stelt ons in staat om programmatisch een criteriumquery-object op te bouwen, waar we verschillende soorten filterregels en logische voorwaarden kunnen toepassen.

Sinds Hibernate 5.2 is de Hibernate Criteria API verouderd en is nieuwe ontwikkeling gericht op de JPA Criteria API. We zullen onderzoeken hoe u Hibernate en JPA kunt gebruiken om criteriumquery's te maken.

2. Maven afhankelijkheden

Om de API te illustreren, gebruiken we de referentie-JPA-implementatie - Hibernate.

Om Hibernate te gebruiken, moet u de nieuwste versie ervan aan uw pom.xml het dossier:

 org.hibernate hibernate-core 5.3.2.Final 

De nieuwste versie van Hibernate is hier te vinden.

3. Eenvoudig voorbeeld met criteria

Laten we beginnen met te kijken hoe u gegevens kunt ophalen met behulp van criteriumquery's. We zullen bekijken hoe we alle instanties van een bepaalde klasse uit de database kunnen halen.

We hebben een Item klasse die het tupel vertegenwoordigt "ITEM" in de database:

public class Item implementeert Serializable {private Integer itemId; private String itemName; private String itemDescription; privé Geheel getal itemPrice; // standaard setters en getters}

Laten we eens kijken naar een eenvoudige criteriaquery die alle rijen met "ITEM" uit de database:

Sessiesessie = HibernateUtil.getHibernateSession (); CriteriaBuilder cb = session.getCriteriaBuilder (); CriteriaQuery cr = cb.createQuery (Item.class); Root root = cr.from (Item.class); cr.select (root); Queryquery = session.createQuery (cr); Lijstresultaten = query.getResultList ();

De bovenstaande zoekopdracht is een eenvoudige demonstratie van hoe u aan alle items kunt komen. Laten we eens kijken wat er is gedaan, stap voor stap:

  1. Maak een instantie van Sessie van de SessionFactory voorwerp
  2. Maak een instantie van CriteriaBuilder door het getCriteriaBuilder () methode
  3. Maak een instantie van CriteriaQuery door het CriteriaBuildercreateQuery () methode
  4. Maak een instantie van Vraag door het SessiecreateQuery () methode
  5. Bel de getResultList () methode van de vraag object dat ons de resultaten geeft

Nu we de basis hebben besproken, gaan we verder met enkele van de kenmerken van criteriumquery:

3.1. Gebruik makend van Uitdrukkingen

De CriteriaBuilder kan worden gebruikt om queryresultaten te beperken op basis van specifieke voorwaarden. Door het gebruiken van CriteriaQuery waarbij () methode en bieden Uitdrukkingen gemaakt door CriteriaBuilder.

Hier zijn enkele voorbeelden van veelgebruikte Uitdrukkingen:

Om artikelen te krijgen met een prijs hoger dan 1000:

cr.select (root) .where (cb.gt (root.get ("itemPrice"), 1000));

Vervolgens items krijgen met stuksprijs minder dan 1000:

cr.select (root) .where (cb.lt (root.get ("itemPrice"), 1000));

Items met itemNames bevatten Stoel:

cr.select (root) .where (cb.like (root.get ("itemName"), "% chair%"));

Records met stuksprijs tussen 100 en 200:

cr.select (root) .where (cb.between (root.get ("itemPrice"), 100, 200));

Om te controleren of de gegeven eigenschap null is:

cr.select (root) .where (cb.isNull (root.get ("itemDescription")));

Om te controleren of de gegeven eigenschap niet null is:

cr.select (root) .where (cb.isNotNull (root.get ("itemDescription")));

U kunt ook de methoden gebruiken is leeg() en is niet leeg() om te testen of a Lijst binnen een klas is leeg of niet.

Nu komt onvermijdelijk de vraag of we twee of meer van de bovenstaande vergelijkingen kunnen combineren of niet. Het antwoord is natuurlijk ja - de Criteria API stelt ons in staat om expressies eenvoudig aan elkaar te koppelen:

Predikaat [] predikaten = nieuw predikaat [2]; predikaten [0] = cb.isNull (root.get ("itemDescription")); predikaten [1] = cb.like (root.get ("itemName"), "chair%"); cr.select (root) .where (predikaten);

Om twee uitdrukkingen toe te voegen met logische bewerkingen:

Predikaat groterThanPrice = cb.gt (root.get ("itemPrice"), 1000); Predicaat chairItems = cb.like (root.get ("itemName"), "Chair%");

Artikelen waaraan de hierboven gedefinieerde voorwaarden zijn gekoppeld Logische OF:

cr.select (root) .where (cb.or (majorThanPrice, chairItems));

Om items te krijgen die overeenkomen met de hierboven gedefinieerde voorwaarden Logisch EN:

cr.select (root) .where (cb.and (majorThanPrice, chairItems));

3.2. Sorteren

Nu we het basisgebruik van Criteria, laten we eens kijken naar de sorteerfunctionaliteiten van Criteria.

In het volgende voorbeeld rangschikken we de lijst in oplopende volgorde van de naam en vervolgens in aflopende volgorde van de prijs:

cr.orderBy (cb.asc (root.get ("itemName")), cb.desc (root.get ("itemPrice")));

In de volgende sectie zullen we bekijken hoe u geaggregeerde functies kunt uitvoeren.

3.3. Projecties, aggregaten en groeperingsfuncties

Tot dusver hebben we de meeste basisonderwerpen behandeld. Laten we nu eens kijken naar de verschillende geaggregeerde functies:

Krijg het aantal rijen:

CriteriaQuery cr = cb.createQuery (Long.class); Root root = cr.from (Item.class); cr.select (cb.count (root)); Queryquery = session.createQuery (cr); Lijst itemProjected = query.getResultList ();

Het volgende is een voorbeeld van geaggregeerde functies:

Aggregaat functie voor Gemiddelde:

CriteriaQuery cr = cb.createQuery (Double.class); Root root = cr.from (Item.class); cr.select (cb.avg (root.get ("itemPrice"))); Queryquery = session.createQuery (cr); Lijst avgItemPriceList = query.getResultList ();

Andere nuttige aggregatiemethoden die beschikbaar zijn, zijn som(), max (), min (), tellen () enz.

3.4. Criteria Update

Vanaf JPA 2.1 is er ondersteuning voor het uitvoeren van database-updates met behulp van de Criteria API.

Criteria Update heeft een set () methode die kan worden gebruikt om nieuwe waarden voor databaserecords op te geven:

CriteriaUpdate criteriaUpdate = cb.createCriteriaUpdate (Item.class); Root root = criteriaUpdate.from (Item.class); criteriaUpdate.set ("itemPrice", newPrice); criteriaUpdate.where (cb.equal (root.get ("itemPrice"), oldPrice)); Transactietransactie = session.beginTransaction (); session.createQuery (criteriaUpdate) .executeUpdate (); transactie.commit ();

In het bovenstaande fragment maken we een instantie van Criteria Update van de CriteriaBuilder en gebruik zijn set () methode om nieuwe waarden op te geven voor de stuksprijs. Om meerdere eigenschappen bij te werken, hoeven we alleen maar het set () methode meerdere keren.

3.5. CriteriaVerwijderen

CriteriaVerwijderen, zoals de naam al aangeeft, maakt het een verwijderbewerking mogelijk met behulp van de Criteria API. Het enige dat we nodig hebben, is een instantie van CriteriaVerwijderen en gebruik de waar() methode om beperkingen toe te passen:

CriteriaDelete criteriaDelete = cb.createCriteriaDelete (Item.class); Root root = criteriaDelete.from (Item.class); criteriaDelete.where (cb.greaterThan (root.get ("itemPrice"), targetPrice)); Transactietransactie = session.beginTransaction (); session.createQuery (criteriaDelete) .executeUpdate (); transactie.commit ();

4. Voordeel ten opzichte van HQL

In de vorige secties hebben we besproken hoe u criteriumquery's kunt gebruiken.

Duidelijk, Het belangrijkste en meest hardnekkige voordeel van Criteria-query's ten opzichte van HQL is de mooie, schone, objectgeoriënteerde API.

We kunnen eenvoudig meer flexibele, dynamische zoekopdrachten schrijven in vergelijking met gewone HQL. De logica kan worden geherstructureerd met de IDE en heeft alle veiligheidsvoordelen van de Java-taal zelf.

Er zijn natuurlijk ook enkele nadelen, vooral bij complexere joins.

Dus over het algemeen zullen we de beste tool voor de klus moeten gebruiken - dat kan in de meeste gevallen de Criteria API zijn, maar er zijn zeker gevallen waarin we een lager niveau moeten gaan.

5. Conclusie

In dit artikel hebben we ons gericht op de basisprincipes van criteriumquery's in Hibernate en JPA, en ook op enkele van de geavanceerde functies van de API.

De code die hier wordt besproken, is beschikbaar in de Github-repository.