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
- Ha nincs benne semmi:
- 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: ...
- ha nincs:
- 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
- http://docs.oracle.com/javaee/6/api/
- David Heffelfinger: Java EE 6 with GlassFish 3 Application Server, (Packt Publishing)
Criteria API
- http://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/Criteria
- http://docs.oracle.com/javaee/6/tutorial/doc/gjivm.html
- http://weblogs.java.net/blog/lancea/archive/2009/12/15/generating-jpa-20-static-metamodel-classes-using-eclipselink-20-and-n