Child pages
  • JPA 2.0 Criteria API
Skip to end of metadata
Go to start of metadata

Bevezetés

A JPA 2.0 egyik legfontosabb újdonsága a Criteria API. Adatbázisból történő lekérdezésekre és adatmódosításra használható, ugyanúgy, mint a JPQL, csak Java nyelven állítjuk vele össze a lekérdezéseket. A szövegben előforduló mintaprogramok EclipseLink 2.3.2-vel lettek tesztelve. A függelékben megtalálható a mintaprogramokban használt táblák szerkezete és a mintaprogramok kipróbálásához használt Eclipse projekt összeállítása.

Problémák a JPQL-lel

Mivel a JPQL String-ként tárolja a lekérdezéseket, az alábbi problémák merülnek fel:

  • A fordító nem tudja ellenőrizni a JPQL szintaxisát.
  • Dinamikusan (runtime) csak String konkatenációval állítható össze lekérdezés.

Egyszerű lekérdezés egy táblából

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BaseDataType> cq = cb.createQuery(BaseDataType.class);
// Root<BaseDataType> r = cq.from(BaseDataType.class);
TypedQuery<BaseDataType> tq = em.createQuery(cq);
List<BaseDataType> results = tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getName());
}

A Criteria API használatakor először is szükségünk van egy CriteriaBuilder példányra az EntityManager-től. A CriteriaBuilder-ből példányosítunk egy CriteriaQuery-t. A createQuery metódusnak átadott BaseDataType.class határozza meg, hogy futtatáskor a CriteriaQuery eredményének mi legyen a típusa. A CriteriaQuery cq.from metódusával megadhatnánk azt az entitást, amiből a lekérdezés történik. Ennek az eredménye egy Root példány, ami JPQL-ben a FROM után szereplő entitásnak felel meg. A Root-ra akkor is szükség van, ha külön-külön akarunk hivatkozni az entitás oszlopaira. Ha nem hívjuk meg a cq.from metódust, akkor a cb.createQuery metódusnál megadott osztály az alapértelmezett. JPQL megfelelője:

EntityManager em = emf.createEntityManager();
TypedQuery<BaseDataType> tq = em.createQuery(
           "SELECT b FROM BaseDataType b",
           BaseDataType.class);
List<BaseDataType> results =tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getName());
}

Adott oszlopok lekérdezése egy táblából

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
cq.select(cb.array(r.get("id"), r.get("name")));
// cq.multiselect(r.get("id"), r.get("name"));
TypedQuery<Object[]> tq = em.createQuery(cq);
List<Object[]> results = tq.getResultList();
for (Object[] result : results) {
           System.out.println(result[0] + " " + result[1]);
}

Adott oszlopokat többféle módon kérdezhetünk le a Criteria API-val:

  • Array: A lekérdezés eredményéből soronként egy Object[] tömböt csinál, melynek az elemei tartalmazzák az oszlopok értékeit. A fenti példa ezt mutatja be.
  • Tuple: Tuple példányokba teszi be a sorokat, amelyeknek a get metódusával kérdezhető le az oszlopok tartalma: tuple.get(0), tuple.get(1)
  • Construct: Magunk definiált objektum példányába teszi bele az eredmény sorait.
  • Multiselect: A CriteriaQuery típusától függően, ami <Object[]>, <Tuple>, <SajatObject> lehet, hajt végre array, tuple vagy construct lekérdezést. A kommentezett rész ezt mutatja be

JPQL megfelelője:

EntityManager em = emf.createEntityManager();
TypedQuery<Object[]> tq = em.createQuery(
           "SELECT b.id, b.name FROM BaseDataType b", Object[].class);
List<Object[]> results = tq.getResultList();
for (Object[] result : results) {
           System.out.println(result[0] + " " + result[1]);
}

Ugyanennek a lekérdezésnek a Multiselect-es változatához először létrehozunk egy BaseDataTypeVO value object osztályt:

public class BaseDataTypeVO {
            private long id;
            private String name;
            public BaseDataTypeVO(long id, String name) {
                           this.id = id;
                           this.name = name;
}
...

És ennek a felhasználásával állítjuk elő a lekérdezést:

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BaseDataTypeVO> cq =
           cb.createQuery(BaseDataTypeVO.class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
cq.multiselect(r.get("id"), r.get("name"));
TypedQuery<BaseDataTypeVO> tq = em.createQuery(cq);
List<BaseDataTypeVO> results = tq.getResultList();
for (BaseDataTypeVO result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

Where feltétel

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BaseDataType> cq = cb.createQuery(BaseDataType.class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
Path<String> p = r.get("name");
Predicate p1 = cb.like(p, "c%");
Predicate p2 = cb.like(p, "p%");
cq.where(cb.or(p1, p2));
TypedQuery<BaseDataType> tq = em.createQuery(cq);
List<BaseDataType> results = tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

A fent látható lekérdezés azokat a BaseDataType-okat adja vissza, melyek name attribútuma c-vel vagy p-vel kezdődik. A Root példánytól kérünk egy Path példányt, amit felhasználhatunk a lekérdezés különböző részeinek az összeállításában az entitás egy attribútumának jelölésére. A lekérdezés Where feltételének összeállítására a CriteriaBuilder metódusait (like, or) használjuk. Az összeállított Where feltételt végül a CriteriaQuery where metódusának adjuk át. JPQL megfelelője:

EntityManager em = emf.createEntityManager();
TypedQuery<BaseDataType> tq = em.createQuery(
           "SELECT b FROM BaseDataType b " +
           "WHERE b.name LIKE :p1 OR b.name LIKE :p2",
           BaseDataType.class);
tq.setParameter("p1", "c%");
tq.setParameter("p2", "p%");
List<BaseDataType> results =tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

Where feltétel collection típusú paraméterrel

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BaseDataType> cq = cb.createQuery(BaseDataType.class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
List<Integer> ids = new ArrayList<Integer>();
ids.add(10);
ids.add(11);
ids.add(12);
cq.where(r.get("id").in(ids));
TypedQuery<BaseDataType> tq = em.createQuery(cq);
List<BaseDataType> results = tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

A fenti lekérdezéssel azokat a BaseDataType-okat kérdezzük le, melyeknek az azonosítója 10, 11 vagy 12. JPQL megfelelője:

EntityManager em = emf.createEntityManager();
TypedQuery<BaseDataType> tq = em.createQuery(
           "SELECT b FROM BaseDataType b " +
           "WHERE b.id IN :p1 ",
           BaseDataType.class);
List<Integer> ids = new ArrayList<Integer>();
ids.add(10);
ids.add(11);
ids.add(12);
tq.setParameter("p1", ids);
List<BaseDataType> results =tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

Dinamikusan összeállított lekérdezés

String name = null;
name = "non";
EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BaseDataType> cq = cb.createQuery(BaseDataType.class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
List<Predicate> predicateList = new ArrayList<Predicate>();
predicateList.add(cb.isNotNull(r.<Integer>get("id")));
if (name != null && name.length() > 0) {
           String pattern = "%" + name.toUpperCase() + "%";
           predicateList.add(cb.like(cb.upper(r.<String>get("name")), pattern));
}
Predicate[] predicates = new Predicate[predicateList.size()];
predicateList.toArray(predicates);
cq.where(predicates);
TypedQuery<BaseDataType> tq = em.createQuery(cq);
List<BaseDataType> results = tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

 A fenti lekérdezés azt mutatja be, amikor nem ismerjük pontosan a feltételek számát, így a CriteriaQuery where metódusának egy Predicate[] tömböt adunk át. Az átadott Predicate-ek között AND kapcsolat fog megvalósulni. JPQL megfelelője:

String name = null;
name = "non";
EntityManager em = emf.createEntityManager();
StringBuilder sb = new StringBuilder(
           "SELECT b FROM BaseDataType b WHERE b.id IS NOT NULL "
);
if (name != null && name.length() > 0) {
           sb.append(" AND UPPER(b.name) LIKE :p1 ");
}
TypedQuery<BaseDataType> tq =
           em.createQuery(sb.toString(), BaseDataType.class);
if (name != null && name.length() > 0) {
           tq.setParameter("p1", "%" + name.toUpperCase() + "%");
}
List<BaseDataType> results = tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

Lekérdezés több táblából

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
Join<BaseDataType, BaseData> j = r.join("baseData");
cq.multiselect(r.get("name"), j.get("value"));
TypedQuery<Object[]> tq = em.createQuery(cq);
List<Object[]> results = tq.getResultList();
for (Object[] result : results) {
           System.out.println(result[0] + " " + result[1]);
}

A Root példányhoz történő összefűzéssel több táblás lekérdezést valósíthatunk meg. Az eredményül kapott Join objektum segítségével hivatkozhatunk az összefűzött entitás mezőire. A join metódusnak egy JoinType attribútumot is meg lehet adni:

Join<BaseDataType, BaseData> j = r.join("baseData", JoinType.INNER);

A JoinType lehetséges értékei: INNER, LEFT, RIGHT. Az INNER az alapértelmezett. JPQL megfelelője:

EntityManager em = emf.createEntityManager();
TypedQuery<Object[]> tq = em.createQuery(
           "SELECT bdt.name, bd.value FROM BaseDataType bdt " +
           "JOIN bdt.baseData bd",
           Object[].class);
List<Object[]> results = tq.getResultList();
for (Object[] result : results) {
           System.out.println(result[0] + " " + result[1]);
}

Lekérdezés több, entity szinten nem összekapcsolt táblából

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
Root<BaseDataType> r1 = cq.from(BaseDataType.class);
Root<BaseData> r2 = cq.from(BaseData.class);
cq.where(cb.equal(r1.get("id"), r2.get("id")));
cq.multiselect(r1.get("id"), r1.get("name"), r2.get("id"), r2.get("value"));
TypedQuery<Object[]> tq = em.createQuery(cq);
List<Object[]> results = tq.getResultList();
for (Object[] result : results) {
           System.out.println(
                      result[0] + " " + result[1] + " " + result[2] + " " + result[3]
           );
}

Ha olyan attribútumok mentén akarunk két entitást összefűzni, amik szerint entitás szinten nincsenek kapcsolatban, akkor két Root példányt kell létrehoznunk, és ezeket Where feltétellel kell összekapcsolnunk. A Where feltétel összeállításakor figyeljünk arra, hogy a két entitás két összekapcsolandó attribútuma azonos típusú legyen pl: long. Ha a Where feltételben nem kapcsoljuk össze a két entitást, akkor Descartes - szorzatot hozunk létre. A fenti, – üzletileg nem túl értelmes – példában BaseDataType.id=BaseData.id alapján kapcsolom össze a két entitást. JPQL megfelelője:

EntityManager em = emf.createEntityManager();
TypedQuery<Object[]> tq = em.createQuery(
           "SELECT bdt.id, bdt.name, bd.id, bd.value " +
           "FROM BaseDataType bdt, BaseData bd " +
           "WHERE bdt.id = bd.id",
           Object[].class);
List<Object[]> results = tq.getResultList();
for (Object[] result : results) {
           System.out.println(
                      result[0] + " " + result[1] + " " + result[2] + " " + result[3]
           );
}

Subquery, Exists

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BaseDataType> cq = cb.createQuery(BaseDataType.class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
Subquery<BaseData> subQuery = cq.subquery(BaseData.class);
Root<BaseData> subQueryRoot = subQuery.from(BaseData.class);
Predicate p1 = cb.like(subQueryRoot.<String>get("value"), "%fix%");
Predicate p2 = cb.equal(r.get("baseData"), subQueryRoot);
subQuery.where(cb.and(p1, p2));
cq.where((cb.exists(subQuery)));
TypedQuery<BaseDataType> tq = em.createQuery(cq);
List<BaseDataType> results = tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

Azokat a BaseDataType-okat adja vissza, melyekhez tartozik olyan BaseData, aminek a value mezőjében szerepel a "fix" String. EXISTS-el kapcsolja össze a két táblát Subquery segítségével. A BaseDataType entitásban a baseData mező típusa Set<BaseData>. De ez nem okoz problémát a Predicate p2 meghatározásánál, ahol a két entitást összekötjük az equal metódussal. Az összekötést a másik irányból is megtehetnénk:

Predicate p2 = cb.equal(r, subQueryRoot.get("baseDataType"));

JPQL megfelelője:

EntityManager em = emf.createEntityManager();
String query =
           "SELECT bdt " +
           "FROM BaseDataType bdt " +
           "WHERE EXISTS ( " +
           "SELECT bd FROM BaseData bd WHERE bdt.baseData = bd " +
           "AND bd.value LIKE :p1 " +
           ")";
TypedQuery<BaseDataType> tq = em.createQuery(query,
           BaseDataType.class);
tq.setParameter("p1", "%fix%");
List<BaseDataType> results = tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

Group by, Order by

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
Join<BaseDataType, BaseData> j = r.join("baseData");
Path<String> p = r.get("name");
cq.groupBy(p);
cq.orderBy(cb.asc(p));
cq.multiselect(r.get("name"), cb.count(r));
TypedQuery<Object[]> tq = em.createQuery(cq);
List<Object[]> results = tq.getResultList();
for (Object[] result : results) {
           System.out.println(result[0] + " " + result[1]);
}

A lekérdezés Group by és Order by részének összeállításához is a korábban megismert Path példányt és a CriteriaBuilder asc metódusát használjuk. Az összeállított kifejezéseket végül a CriteriaQuery groupBy és orderBy metódusainak adjuk át. A CriteriaQuery multiselect részében a CriteriaBuilder segítségével egy count kifejezést is összeállítunk. JPQL megfelelője:

EntityManager em = emf.createEntityManager();
TypedQuery<Object[]> tq = em.createQuery(
           "SELECT bdt.name, COUNT(bdt) FROM BaseDataType bdt " +
           "JOIN bdt.baseData bd GROUP BY bdt.name ORDER BY bdt.name",
           Object[].class);
List<Object[]> results = tq.getResultList();
for (Object[] result : results) {
           System.out.println(result[0] + " " + result[1]);
}

Max

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BigDecimal> cq = cb.createQuery(BigDecimal.class);
Root<BaseData> r = cq.from(BaseData.class);
cq.multiselect(cb.max(r.<BigDecimal>get("id")));
TypedQuery<BigDecimal> tq = em.createQuery(cq);
System.out.println("result: " + tq.getSingleResult());

A max függvény használatát mutatja be. Érdekesség, hogy a Criteria API BigDecimal-t használ, a JPQL pedig Long-ot. JPQL megfelelője:

EntityManager em = emf.createEntityManager();
TypedQuery<Long> tq = em.createQuery(
               "SELECT max(bd.id) FROM BaseData bd ",
               Long.class);
System.out.println("result: " + tq.getSingleResult());

Query casting

...
Root<BaseDataType> r = cq.from(BaseDataType.class);
Join<BaseDataType, BaseData> j = r.join("baseData");
Path<SpecialBaseData> p1 =
                         (Path<SpecialBaseData>)j.as(SpecialBaseData.class);
...

Az Expression.as(type) segítségével leszármaztatott osztályként kérdezhetünk le az entity szinten ősosztályként összefűzött entitást. A cast-olással a Join node véglegesen átváltozik SpecialBaseDatává. A SpecialBaseData osztály hiányzik a függelékből:

package criteriaapidemo;
public class SpecialBaseData extends BaseData {}

JPQL megfelelője:

...
TypedQuery<Object[]> tq = em.createQuery(
           "SELECT bdt.name, COUNT(bdt) FROM BaseDataType bdt " +
           "JOIN TREAT(bdt.baseData as SpecialBaseData) bd " +
           "GROUP BY bdt.name ORDER BY bdt.name",
           Object[].class);
...

Metamodel

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BaseDataType> cq = cb.createQuery(BaseDataType.class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
Metamodel m = em.getMetamodel();
EntityType<BaseDataType> et = m.entity(BaseDataType.class);
SingularAttribute<BaseDataType, String> sa =
           et.getDeclaredSingularAttribute("name", String.class);
Path<String> p = r.get(sa);
// Path<String> p = r.get("name");
Predicate p1 = cb.like(p, "c%");
Predicate p2 = cb.like(p, "p%");
cq.where(cb.or(p1, p2));
TypedQuery<BaseDataType> tq = em.createQuery(cq);
List<BaseDataType> results = tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

A JPA 2.0 újdonsága a Metamodel API is. A Metamodel API segítségével dinamikusan kérdezhetjük le egy entitás attribútumait. Most a Where feltétel bemutatásánál használt lekérdezést láthatjuk, azzal a változtatással, hogy a BaseDataType entitás „name” attribútumát Metamodel segítségével állítjuk elő. A Metamodel használatához az EntityManagertől kérhetünk egy Metamodel objektumot. A Metamodelből egy EntityType-ot kérhetünk, ami segítségével az entitás perzisztens attribútumai között böngészhetünk. A SingularAttribute felel meg az entitás egy szimpla Object attribútumának. De ha például Collection típusú attribútumot kérdeznénk le, akkor az EntityType getDeclaredCollection metódusát használhatjuk, ami CollectionAttribute típusú objektumot ad vissza. A SingularAtribute felhasználásával a Root objektumtól kérünk egy Path objektumot, amit felhasználhatunk a lekérdezés különböző részeinek az összeállításában az entitás egy attribútumának jelölésére. Kikommentezve látható a Path példány előállításának módja Metamodel nélkül. Az ezután jövő sorok és a lekérdezés JPQL megfelelője megegyeznek a Where feltételnél látottakkal.

Metamodel strongly typed változat

A Metamodel API segítségével azontúl, hogy dinamikusan lekérdezhetjük egy entitás attribútumait, lehetőségünk van strongly typed lekérdezések írására is. Most a Where feltétel és a Metamodel ismertetésénél használt lekérdezés strongly typed Metamodel-es változatát állítjuk össze. Első lépésként StaticMetamodel osztályokat kell építenünk az entitás osztályaink mellé. Ezeket az osztályokat célszerű generálni, amihez az EclipseLink annotation processorát vesszük igénybe. A következő parancsot közvetlenül a projekt könyvtárunkból kell futtatni – amiben az src könyvtár van. De előtte pontosítsuk az eclipselink.jar és a javax.persistence...jar helyét. A parancsot egy sorba kell leírni, célszerű egy bat fájlba:

javac -processor org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor

Futtatás után egy BaseData_.java és egy BaseDataType_.java keletkezik:

@Generated(value="EclipseLink-2.3.2.v20111125-r10461", date="2012-03-02T21:50:47")
@StaticMetamodel(BaseDataType.class)
public class BaseDataType_ {
    public static volatile SingularAttribute<BaseDataType, Long> id;
    public static volatile SingularAttribute<BaseDataType, String> name;
    public static volatile SetAttribute<BaseDataType, BaseData> baseData;
}

  

@Generated(value="EclipseLink-2.3.2.v20111125-r10461", date="2012-03-02T21:50:47")
@StaticMetamodel(BaseData.class)
public class BaseData_ {
    public static volatile SingularAttribute<BaseData, Long> id;
    public static volatile SingularAttribute<BaseData, BaseDataType> baseDataType;
    public static volatile SingularAttribute<BaseData, String> value;
}

A BaseDataType_ osztály felhasználásával így állíthatjuk össze a lekérdezést:

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BaseDataType> cq = cb.createQuery(BaseDataType.class);
Root<BaseDataType> r = cq.from(BaseDataType.class);
Path<String> p = r.get(BaseDataType_.name);
Predicate p1 = cb.like(p, "c%");
Predicate p2 = cb.like(p, "p%");
cq.where(cb.or(p1, p2));
TypedQuery<BaseDataType> tq = em.createQuery(cq);
List<BaseDataType> results = tq.getResultList();
for (BaseDataType result : results) {
           System.out.println(result.getId() + " " + result.getName());
}

A lekérdezésben csak a Path előállítása változott.

Speciális karakterek escape-elése like-os keresésnél

public static String escapeLikeExpression(final String expression) {
               return expression.replace("!", "'!").replace("_", "!_")
                               .replace("%", "!%");
}    

Függelék 1: Demo project összeállítása

Előfeltételek

  • JDK 1.6
  • Eclipse
  • Oracle XE
  • BASE_DATA, BASE_DATA_TYPE tábla

Eclipse indít

Indítsuk el az Eclipse környezetet.

Hozzuk létre a projektet

  • File > New > JPA Project
  • Project name: CriteriaApiDemo
  • Location: C:\MyProjects\CriteriaApiDemo
  • Target runtime: jdk1.6.0_27
  • Next, Next
  • Platform: EclipseLink 2.3.x
  • Type: User Library
    • Ha nincs benne semmi:
      • Download library... ikon
      • EclipseLink 2.3.2 - Indigo
      • Next
      • I accept the terms of this license.
      • Finish
  • Connection: LocalOracleMaster (local oracle connection kiválaszt a master sémára)
    • ha nincs:
      • Add connection...
      • SID: XE, host: localhost, Port number: 1521, User name: master, Password: ...
  • Discover annotated classes automatically
  • Finish
  • Open JPA perspective: Yes

Vegyük fel projecthez az ojdbc6.jar fájlt

  • CriteriaApiDemo project jobb klikk > Properties > Java Build Path
  • Add External JARs...
  • C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib\ojdbc6.jar
  • OK

Hozzuk létre a JPA entitásokat

  • CriteriaApiDemo project jobb klikk > New > JPA Entities from Tables
  • Connection: LocalOracleMaster
  • Connect icon
  • Schema: MASTER
  • Tables: BASE_DATA, BASE_DATA_TYPE
  • Update class list in persistence.xml legyen becsekkelve
  • Next, Next
  • Key generator: sequence
  • Sequence name: $table_S
  • Package: criteriaapidemo
  • Next, Finish

Állítsuk be az adatforrást

  • JPA Content / persistence.xml
  • Connection fül
    • Transaction type: Resource Local
    • EclipseLink connection pool: Populate from connection...
    • LocalOracleMaster
  • Schema Generation fül
    • DDL generation type: Default (None)

Hozzuk létre a Main class állományt

  • CriteriaApiDemo project jobb klikk > New > Class
  • Package: criteriaapidemo
  • Name: CriteriaApiDemoMain
package criteriaapidemo;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

public class CriteriaApiDemoMain {
            public static void main(String[] args) {
                        EntityManagerFactory emf =
                                   Persistence.createEntityManagerFactory("CriteriaApiDemo");
                        EntityManager em = emf.createEntityManager();
                        CriteriaBuilder cb = em.getCriteriaBuilder();
                        CriteriaQuery<BaseDataType> cq = cb.createQuery(BaseDataType.class);
                        // Root<BaseDataType> r = cq.from(BaseDataType.class);
                        TypedQuery<BaseDataType> tq = em.createQuery(cq);
                        List<BaseDataType> results = tq.getResultList();
                        for (BaseDataType result : results) {
                                   System.out.println(result.getName());
                        }
            }
}

Futtatás

  • CriteriaApiDemoMain jobb klikk > Run as > Java Application

Függelék 2: Adatbázis táblák

CREATE TABLE BASE_DATA_TYPE (
    ID   NUMBER(10,0) NOT NULL ENABLE,
    NAME VARCHAR2(4000 BYTE),
    PRIMARY KEY (ID)
  );

CREATE TABLE BASE_DATA (
    ID                NUMBER(10,0) NOT NULL ENABLE,
    VALUE             VARCHAR2(4000 BYTE),
    BASE_DATA_TYPE_ID NUMBER(10,0),
    PRIMARY KEY (ID),
    CONSTRAINT FK_BASE_DATA_BASE_DATA_TYPE_ID FOREIGN KEY (BASE_DATA_TYPE_ID) REFERENCES BASE_DATA_TYPE (ID)
  );

Irodalom

Java EE

Criteria API

Query casting

      
      
Page viewed times