JPA

此處選用尚硅谷的教程和資料 http://www.atguigu.com/ 感謝其開源
JDBC
JDBC
JPA是什么

Java Persistence API:用于對象持久化的 API
Java EE 5.0 平臺標準的 ORM 規(guī)范,使得應用程序以統(tǒng)一的方式訪問持久層


JPA
JPA和Hibernate的關系

JPA 是 hibernate 的一個抽象(就像JDBC和JDBC驅動的關系):
JPA 是規(guī)范:JPA 本質上就是一種 ORM 規(guī)范,不是ORM 框架 —— 因為 JPA 并未提供 ORM 實現(xiàn),它只是制訂了一些規(guī)范,提供了一些編程的 API 接口,但具體實現(xiàn)則由 ORM 廠商提供實現(xiàn)
Hibernate 是實現(xiàn):Hibernate 除了作為 ORM 框架之外,它也是一種 JPA 實現(xiàn)
從功能上來說, JPA 是 Hibernate 功能的一個子集

JPA 的供應商

JPA 的目標之一是制定一個可以由很多供應商實現(xiàn)的 API,目前Hibernate 3.2+、TopLink 10.1+ 以及 OpenJPA 都提供了 JPA 的實現(xiàn)
Hibernate
JPA 的始作俑者就是 Hibernate 的作者
Hibernate 從 3.2 開始兼容 JPA
OpenJPA
OpenJPA 是 Apache 組織提供的開源項目
TopLink
TopLink 以前需要收費,如今開源了

JPA的優(yōu)勢

標準化: 提供相同的 API,這保證了基于JPA 開發(fā)的企業(yè)應用能夠經(jīng)過少量的修改就能夠在不同的 JPA 框架下運行。
簡單易用,集成方便: JPA 的主要目標之一就是提供更加簡單的編程模型,在 JPA 框架下創(chuàng)建實體和創(chuàng)建 Java 類一樣簡單,只需要使用 javax.persistence.Entity 進行注釋;JPA 的框架和接口也都非常簡單,
可媲美JDBC的查詢能力: JPA的查詢語言是面向對象的,JPA定義了獨特的JPQL,而且能夠支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能夠提供的高級查詢特性,甚至還能夠支持子查詢。
支持面向對象的高級特性: JPA 中能夠支持面向對象的高級特性,如類之間的繼承、多態(tài)和類之間的復雜關系,最大限度的使用面向對象的模型

JPA 包括 3方面的技術

ORM 映射元數(shù)據(jù):JPA 支持 XML 和 JDK 5.0 注解兩種元數(shù)據(jù)的形式,元數(shù)據(jù)描述對象和表之間的映射關系,框架據(jù)此將實體對象持久化到數(shù)據(jù)庫表中。
JPA 的 API:用來操作實體對象,執(zhí)行CRUD操作,框架在后臺完成所有的事情,開發(fā)者從繁瑣的 JDBC和 SQL代碼中解脫出來。
查詢語言(JPQL):這是持久化操作中很重要的一個方面,通過面向對象而非面向數(shù)據(jù)庫的查詢語言查詢數(shù)據(jù),避免程序和具體的 SQL 緊密耦合。

使用JPA持久化對象的步驟

創(chuàng)建 persistence.xml, 在這個文件中配置持久化單元
需要指定跟哪個數(shù)據(jù)庫進行交互;
需要指定 JPA 使用哪個持久化的框架以及配置該框架的基本屬性
創(chuàng)建實體類, 使用 annotation 來描述實體類跟數(shù)據(jù)庫表之間的映射關系.
使用 JPA API 完成數(shù)據(jù)增加、刪除、修改和查詢操作
創(chuàng)建 EntityManagerFactory (對應 Hibernate 中的 SessionFactory);
創(chuàng)建 EntityManager (對應 Hibernate 中的Session);

打開Eclipse 新建JPA項目
1

2
persistence.xml

JPA 規(guī)范要求在類路徑的 META-INF 目錄下放置persistence.xml,文件的名稱是固定的

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="jpa-1" transaction-type="RESOURCE_LOCAL">
        <!-- 
        配置使用什么 ORM 產(chǎn)品來作為 JPA 的實現(xiàn) 
        1. 實際上配置的是  javax.persistence.spi.PersistenceProvider 接口的實現(xiàn)類
        2. 若 JPA 項目中只有一個 JPA 的實現(xiàn)產(chǎn)品, 則也可以不配置該節(jié)點. 
        -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
    
        <!-- 添加持久化類 -->
        <class>com.atguigu.jpa.helloworld.Customer</class>
        <class>com.atguigu.jpa.helloworld.Order</class>
    
        <class>com.atguigu.jpa.helloworld.Department</class>
        <class>com.atguigu.jpa.helloworld.Manager</class>
    
        <class>com.atguigu.jpa.helloworld.Item</class>
        <class>com.atguigu.jpa.helloworld.Category</class>
        
        <!-- 
        配置二級緩存的策略 
        ALL:所有的實體類都被緩存
        NONE:所有的實體類都不被緩存. 
        ENABLE_SELECTIVE:標識 @Cacheable(true) 注解的實體類將被緩存
        DISABLE_SELECTIVE:緩存除標識 @Cacheable(false) 以外的所有實體類
        UNSPECIFIED:默認值,JPA 產(chǎn)品默認值將被使用
        -->
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
    
        <properties>
            <!-- 連接數(shù)據(jù)庫的基本信息 -->
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="1230"/>
            
            <!-- 配置 JPA 實現(xiàn)產(chǎn)品的基本屬性. 配置 hibernate 的基本屬性 -->
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            
            <!-- 二級緩存相關 -->
            <property name="hibernate.cache.use_second_level_cache" value="true"/>
            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
            <property name="hibernate.cache.use_query_cache" value="true"/>
        </properties>
    </persistence-unit>
</persistence>
1
執(zhí)行持久化操作
執(zhí)行持久化操作
JPA基本注解
JPA基本注解
@Entity

@Entity 標注用于實體類聲明語句之前,指出該Java 類為實體類,將映射到指定的數(shù)據(jù)庫表。如聲明一個實體類 Customer,它將映射到數(shù)據(jù)庫中的 customer 表上。

@Table

當實體類與其映射的數(shù)據(jù)庫表名不同名時需要使用 @Table 標注說明,該標注與 @Entity 標注并列使用,置于實體類聲明語句之前,可寫于單獨語句行,也可與聲明語句同行。
@Table 標注的常用選項是 name,用于指明數(shù)據(jù)庫的表名
@Table標注還有一個兩個選項 catalog 和 schema 用于設置表所屬的數(shù)據(jù)庫目錄或模式,通常為數(shù)據(jù)庫名。uniqueConstraints 選項用于設置約束條件,通常不須設置。


Table
@Id

@Id 標注用于聲明一個實體類的屬性映射為數(shù)據(jù)庫的主鍵列。該屬性通常置于屬性聲明語句之前,可與聲明語句同行,也可寫在單獨行上。
@Id標注也可置于屬性的getter方法之前。


Id
@GeneratedValue

@GeneratedValue 用于標注主鍵的生成策略,通過 strategy 屬性指定。默認情況下,JPA 自動選擇一個最適合底層數(shù)據(jù)庫的主鍵生成策略:SqlServer 對應 identity,MySQL 對應 auto increment。
在 javax.persistence.GenerationType 中定義了以下幾種可供選擇的策略:
IDENTITY:采用數(shù)據(jù)庫 ID自增長的方式來自增主鍵字段,Oracle 不支持這種方式;
AUTO: JPA自動選擇合適的策略,是默認選項;
SEQUENCE:通過序列產(chǎn)生主鍵,通過 @SequenceGenerator 注解指定序列名,MySql 不支持這種方式
TABLE:通過表產(chǎn)生主鍵,框架借由表模擬序列產(chǎn)生主鍵,使用該策略可以使應用更易于數(shù)據(jù)庫移植。

@Basic

@Basic 表示一個簡單的屬性到數(shù)據(jù)庫表的字段的映射,對于沒有任何標注的 getXxxx() 方法,默認即為@Basic
fetch: 表示該屬性的讀取策略,有 EAGER 和 LAZY 兩種,分別表示主支抓取和延遲加載,默認為 EAGER.
optional:表示該屬性是否允許為null, 默認為true

@Column

當實體的屬性與其映射的數(shù)據(jù)庫表的列不同名時需要使用@Column 標注說明,該屬性通常置于實體的屬性聲明語句之前,還可與 @Id 標注一起使用。
@Column 標注的常用屬性是 name,用于設置映射數(shù)據(jù)庫表的列名。此外,該標注還包含其它多個屬性,如:unique 、nullable、length 等。
@Column 標注的 columnDefinition 屬性: 表示該字段在數(shù)據(jù)庫中的實際類型.通常 ORM 框架可以根據(jù)屬性類型自動判斷數(shù)據(jù)庫中字段的類型,但是對于Date類型仍無法確定數(shù)據(jù)庫中字段類型究竟是DATE,TIME還是TIMESTAMP.此外,String的默認映射類型為VARCHAR, 如果要將 String 類型映射到特定數(shù)據(jù)庫的 BLOB 或TEXT 字段類型.
@Column標注也可置于屬性的getter方法之前

@Transient

表示該屬性并非一個到數(shù)據(jù)庫表的字段的映射,ORM框架將忽略該屬性.
如果一個屬性并非數(shù)據(jù)庫表的字段映射,就務必將其標示為@Transient,否則,ORM框架默認其注解為@Basic

@Temporal

在核心的 Java API 中并沒有定義 Date 類型的精度(temporal precision). 而在數(shù)據(jù)庫中,表示 Date 類型的數(shù)據(jù)有 DATE, TIME, 和 TIMESTAMP 三種精度(即單純的日期,時間,或者兩者 兼?zhèn)?. 在進行屬性映射時可使用@Temporal注解來調(diào)整精度.

用Table生成主鍵
用Table生成主鍵

用Table生成主鍵
JPA API
JPA API
JPA相關接口/類:Persistence

Persistence 類是用于獲取 EntityManagerFactory 實例。該類包含一個名為 createEntityManagerFactory 的 靜態(tài)方法 。
createEntityManagerFactory 方法有如下兩個重載版本。
帶有一個參數(shù)的方法以 JPA 配置文件 persistence.xml 中的持久化單元名為參數(shù)
帶有兩個參數(shù)的方法:前一個參數(shù)含義相同,后一個參數(shù) Map類型,用于設置 JPA 的相關屬性,這時將忽略其它地方設置的屬性。Map 對象的屬性名必須是 JPA 實現(xiàn)庫提供商的名字空間約定的屬性名。

EntityManagerFactory

EntityManagerFactory 接口主要用來創(chuàng)建 EntityManager 實例。該接口約定了如下4個方法:
createEntityManager():用于創(chuàng)建實體管理器對象實例。
createEntityManager(Map map):用于創(chuàng)建實體管理器對象實例的重載方法,Map 參數(shù)用于提供 EntityManager 的屬性。
isOpen():檢查 EntityManagerFactory 是否處于打開狀態(tài)。實體管理器工廠創(chuàng)建后一直處于打開狀態(tài),除非調(diào)用close()方法將其關閉。
close():關閉 EntityManagerFactory 。 EntityManagerFactory 關閉后將釋放所有資源,isOpen()方法測試將返回 false,其它方法將不能調(diào)用,否則將導致IllegalStateException異常。

EntityManager

在 JPA 規(guī)范中, EntityManager 是完成持久化操作的核心對象。實體作為普通 Java 對象,只有在調(diào)用 EntityManager 將其持久化后才會變成持久化對象。EntityManager 對象在一組實體類與底層數(shù)據(jù)源之間進行 O/R 映射的管理。它可以用來管理和更新 Entity Bean, 根椐主鍵查找 Entity Bean, 還可以通過JPQL語句查詢實體。

實體的狀態(tài):
新建狀態(tài): 新創(chuàng)建的對象,尚未擁有持久性主鍵。
持久化狀態(tài):已經(jīng)擁有持久性主鍵并和持久化建立了上下文環(huán)境
游離狀態(tài):擁有持久化主鍵,但是沒有與持久化建立上下文環(huán)境
刪除狀態(tài): 擁有持久化主鍵,已經(jīng)和持久化建立上下文環(huán)境,但是從數(shù)據(jù)庫中刪除。

find (Class<T> entityClass,Object primaryKey):返回指定的 OID 對應的實體類對象,如果這個實體存在于當前的持久化環(huán)境,則返回一個被緩存的對象;否則會創(chuàng)建一個新的 Entity, 并加載數(shù)據(jù)庫中相關信息;若 OID 不存在于數(shù)據(jù)庫中,則返回一個 null。第一個參數(shù)為被查詢的實體類類型,第二個參數(shù)為待查找實體的主鍵值。

getReference (Class<T> entityClass,Object primaryKey):與find()方法類似,不同的是:如果緩存中不存在指定的 Entity, EntityManager 會創(chuàng)建一個 Entity 類的代理,但是不會立即加載數(shù)據(jù)庫中的信息,只有第一次真正使用此 Entity 的屬性才加載,所以如果此 OID 在數(shù)據(jù)庫不存在,getReference() 不會返回 null 值, 而是拋出EntityNotFoundException

persist (Object entity):用于將新創(chuàng)建的 Entity 納入到 EntityManager 的管理。該方法執(zhí)行后,傳入 persist() 方法的 Entity 對象轉換成持久化狀態(tài)。
如果傳入 persist() 方法的 Entity 對象已經(jīng)處于持久化狀態(tài),則 persist() 方法什么都不做。
如果對刪除狀態(tài)的 Entity 進行 persist() 操作,會轉換為持久化狀態(tài)。
如果對游離狀態(tài)的實體執(zhí)行 persist() 操作,可能會在 persist() 方法拋出 EntityExistException(也有可能是在flush或事務提交后拋出)。

remove (Object entity):刪除實例。如果實例是被管理的,即與數(shù)據(jù)庫實體記錄關聯(lián),則同時會刪除關聯(lián)的數(shù)據(jù)庫記錄。

merge (T entity):merge() 用于處理 Entity 的同步。即數(shù)據(jù)庫的插入和更新操作


圖解

flush ():同步持久上下文環(huán)境,即將持久上下文環(huán)境的所有未保存實體的狀態(tài)信息保存到數(shù)據(jù)庫中。

setFlushMode (FlushModeType flushMode):設置持久上下文環(huán)境的Flush模式。參數(shù)可以取2個枚舉

FlushModeType.AUTO 為自動更新數(shù)據(jù)庫實體,

FlushModeType.COMMIT 為直到提交事務時才更新數(shù)據(jù)庫記錄。

getFlushMode ():獲取持久上下文環(huán)境的Flush模式。返回FlushModeType類的枚舉值。

refresh (Object entity):用數(shù)據(jù)庫實體記錄的值更新實體對象的狀態(tài),即更新實例的屬性值。

clear ():清除持久上下文環(huán)境,斷開所有關聯(lián)的實體。如果這時還有未提交的更新則會被撤消。

contains (Object entity):判斷一個實例是否屬于當前持久上下文環(huán)境管理的實體。
isOpen ():判斷當前的實體管理器是否是打開狀態(tài)。

getTransaction ():返回資源層的事務對象。EntityTransaction實例可以用于開始和提交多個事務。

close ():關閉實體管理器。之后若調(diào)用實體管理器實例的方法或其派生的查詢對象的方法都將拋出 IllegalstateException 異常,除了getTransaction 和 isOpen方法(返回 false)。不過,當與實體管理器關聯(lián)的事務處于活動狀態(tài)時,調(diào)用 close 方法后持久上下文將仍處于被管理狀態(tài),直到事務完成。

createQuery (String qlString):創(chuàng)建一個查詢對象。

createNamedQuery (String name):根據(jù)命名的查詢語句塊創(chuàng)建查詢對象。參數(shù)為命名的查詢語句。

createNativeQuery (String sqlString):使用標準 SQL語句創(chuàng)建查詢對象。參數(shù)為標準SQL語句字符串。

createNativeQuery (String sqls, String resultSetMapping):使用標準SQL語句創(chuàng)建查詢對象,并指定返回結果集 Map的 名稱。

EntityTransaction

EntityTransaction 接口用來管理資源層實體管理器的事務操作。通過調(diào)用實體管理器、的getTransaction方法 獲得其實例。

begin ()
用于啟動一個事務,此后的多個數(shù)據(jù)庫操作將作為整體被提交或撤消。若這時事務已啟動則會拋出 IllegalStateException 異常。

commit ()
用于提交當前事務。即將事務啟動以后的所有數(shù)據(jù)庫更新操作持久化至數(shù)據(jù)庫中。

rollback ()
撤消(回滾)當前事務。即撤消事務啟動后的所有數(shù)據(jù)庫更新操作,從而不對數(shù)據(jù)庫產(chǎn)生影響。

setRollbackOnly ()
使當前事務只能被撤消。

getRollbackOnly ()
查看當前事務是否設置了只能撤消標志。

isActive ()
查看當前事務是否是活動的。如果返回true則不能調(diào)用begin方法,否則將拋出 IllegalStateException 異常;如果返回 false 則不能調(diào)用 commit、rollback、setRollbackOnly 及 getRollbackOnly 方法,否則將拋出 IllegalStateException 異常。

映射關聯(lián)關系
映射關聯(lián)關系

雙向一對多以及多對一映射

雙向一對一映射

雙向一對一不延遲懶加載問題

雙向多對多關聯(lián)關系
使用二級緩存

<shared-cache-mode> 節(jié)點:若 JPA 實現(xiàn)支持二級緩存,該節(jié)點可以配置在當前的持久化單元中是否啟用二級緩存,可配置如下值:
ALL:所有的實體類都被緩存
NONE:所有的實體類都不被緩存.
ENABLE_SELECTIVE:標識 @Cacheable(true) 注解的實體類將被緩存
DISABLE_SELECTIVE:緩存除標識 @Cacheable(false) 以外的所有實體類
UNSPECIFIED:默認值,JPA 產(chǎn)品默認值將被使用

JPQL語言

JPQL語言,即 Java Persistence Query Language 的簡稱。JPQL 是一種和 SQL 非常類似的中間性和對象化查詢語言,它最終會被編譯成針對不同底層數(shù)據(jù)庫的 SQL 查詢,從而屏蔽不同數(shù)據(jù)庫的差異。
JPQL語言的語句可以是 select 語句、update 語句或delete語句,它們都通過 Query 接口封裝執(zhí)行

javax.persistence.Query

Query接口封裝了執(zhí)行數(shù)據(jù)庫查詢的相關方法。調(diào)用 EntityManager 的 createQuery、create NamedQuery 及 createNativeQuery 方法可以獲得查詢對象,進而可調(diào)用 Query 接口的相關方法來執(zhí)行查詢操作。
Query接口的主要方法
int executeUpdate()
用于執(zhí)行update或delete語句。
List getResultList()
用于執(zhí)行select語句并返回結果集實體列表。
Object getSingleResult()
用于執(zhí)行只返回單個結果實體的select語句。
Query setFirstResult(int startPosition)
用于設置從哪個實體記錄開始返回查詢結果。
Query setMaxResults(int maxResult)
用于設置返回結果實體的最大數(shù)。與setFirstResult結合使用可實現(xiàn)分頁查詢。
Query setFlushMode(FlushModeType flushMode)
設置查詢對象的Flush模式。參數(shù)可以取2個枚舉值:FlushModeType.AUTO 為自動更新數(shù)據(jù)庫記錄,F(xiàn)lushMode Type.COMMIT 為直到提交事務時才更新數(shù)據(jù)庫記錄。
setHint(String hintName, Object value)
設置與查詢對象相關的特定供應商參數(shù)或提示信息。參數(shù)名及其取值需要參考特定 JPA 實現(xiàn)庫提供商的文檔。如果第二個參數(shù)無效將拋出IllegalArgumentException異常。
setParameter(int position, Object value)
為查詢語句的指定位置參數(shù)賦值。Position 指定參數(shù)序號,value 為賦給參數(shù)的值。
setParameter(int position, Date d, TemporalType type)
為查詢語句的指定位置參數(shù)賦 Date 值。Position 指定參數(shù)序號,value 為賦給參數(shù)的值,temporalType 取 TemporalType 的枚舉常量,包括 DATE、TIME 及 TIMESTAMP 三個,,用于將 Java 的 Date 型值臨時轉換為數(shù)據(jù)庫支持的日期時間類型(java.sql.Date、java.sql.Time及java.sql.Timestamp)。
setParameter(int position, Calendar c, TemporalType type)
為查詢語句的指定位置參數(shù)賦 Calenda r值。position 指定參數(shù)序號,value 為賦給參數(shù)的值,temporalType 的含義及取舍同前。
setParameter(String name, Object value)
為查詢語句的指定名稱參數(shù)賦值。
setParameter(String name, Date d, TemporalType type)
為查詢語句的指定名稱參數(shù)賦 Date 值。用法同前。
setParameter(String name, Calendar c, TemporalType type)
為查詢語句的指定名稱參數(shù)設置Calendar值。name為參數(shù)名,其它同前。該方法調(diào)用時如果參數(shù)位置或參數(shù)名不正確,或者所賦的參數(shù)值類型不匹配,將拋出 IllegalArgumentException 異常。

select語句

select語句用于執(zhí)行查詢。其語法可表示為:
select_clause
form_clause
[where_clause]
[groupby_clause]
[having_clause]
[orderby_clause]

select-from 子句

from 子句是查詢語句的必選子句。
Select 用來指定查詢返回的結果實體或實體的某些屬性
From 子句聲明查詢源實體類,并指定標識符變量(相當于SQL表的別名)。
如果不希望返回重復實體,可使用關鍵字 distinct 修飾。select、from 都是 JPQL 的關鍵字,通常全大寫或全小寫,建議不要大小寫混用。

查詢所有實體

查詢所有實體的 JPQL 查詢字串很簡單,例如:
select o from Order o 或 select o from Order as o
關鍵字 as 可以省去。
標識符變量的命名規(guī)范與 Java 標識符相同,且區(qū)分大小寫。
調(diào)用 EntityManager 的 createQuery() 方法可創(chuàng)建查詢對象,接著調(diào)用 Query 接口的 getResultList() 方法就可獲得查詢結果集。例如:

Query query = entityManager.createQuery( "select o from Order o"); 
List orders = query.getResultList();
Iterator iterator = orders.iterator();
while( iterator.hasNext() ) {
    // 處理Order
}

where子句用于指定查詢條件,where跟條件表達式。例:

select o from Orders o where o.id = 1
select o from Orders o where o.id > 3 and o.confirm = 'true'    
select o from Orders o where o.address.streetNumber >= 123

JPQL也支持包含參數(shù)的查詢,例如:

select o from Orders o where o.id = :myId
select o from Orders o where o.id = :myId and o.customer = :customerName

注意:參數(shù)名前必須冠以冒號(:),執(zhí)行查詢前須使用Query.setParameter(name, value)方法給參數(shù)賦值。
也可以不使用參數(shù)名而使用參數(shù)的序號,例如:
select o from Order o where o.id = ?1 and o.customer = ?2
其中 ?1 代表第一個參數(shù),?2 代表第一個參數(shù)。在執(zhí)行查詢之前需要使用重載方法Query.setParameter(pos, value) 提供參數(shù)值。

Query query = entityManager.createQuery( "select o from     
Orders o where o.id = ?1 and o.customer = ?2" );
query.setParameter( 1, 2 );
query.setParameter( 2, "John" );
List orders = query.getResultList();
… …

where條件表達式中可用的運算符基本上與SQL一致,包括:
算術運算符:+ - * / +(正) -(負)
關系運算符:== <> > >= < <= between…and like in is null 等
邏輯運算符: and or  not

where 字句實例
下面是一些常見查詢表達式示例:
// 以下語句查詢 Id 介于 100 至 200 之間的訂單。
select o from Orders o where o.id between 100 and 200
// 以下語句查詢國籍為的 'US'、'CN'或'JP' 的客戶。
select c from Customers c where c.county in ('US','CN','JP')
// 以下語句查詢手機號以139開頭的客戶。%表示任意多個字符序列,包括0個。
select c from Customers c where c.phone like '139%'
// 以下語句查詢名字包含4個字符,且234位為ose的客戶。_表示任意單個字符。
select c from Customers c where c.lname like '_ose' 
// 以下語句查詢電話號碼未知的客戶。Nul l用于測試單值是否為空。
select c from Customers c where c.phone is null
// 以下語句查詢尚未輸入訂單項的訂單。empty用于測試集合是否為空。
select o from Orders o where o.orderItems is empty
查詢部分屬性

如果只須查詢實體的部分屬性而不需要返回整個實體。例如:
select o.id, o.customerName, o.address.streetNumber from Order o order by o.id
執(zhí)行該查詢返回的不再是Orders實體集合,而是一個對象數(shù)組的集合(Object[]),集合的每個成員為一個對象數(shù)組,可通過數(shù)組元素訪問各個屬性。

使用 Hibernate 的查詢緩存
使用 Hibernate 的查詢緩存
order by子句

order by子句用于對查詢結果集進行排序。和SQL的用法類似,可以用 “asc“ 和 "desc“ 指定升降序。如果不顯式注明,默認為升序。

select o from Orders o order by o.id
select o from Orders o order by o.address.streetNumber desc
select o from Orders o order by o.customer asc, o.id desc
group by子句與聚合查詢

group by 子句用于對查詢結果分組統(tǒng)計,通常需要使用聚合函數(shù)。常用的聚合函數(shù)主要有 AVG、SUM、COUNT、MAX、MIN 等,它們的含義與SQL相同。例如:
select max(o.id) from Orders o
沒有 group by 子句的查詢是基于整個實體類的,使用聚合函數(shù)將返回單個結果值,可以使用Query.getSingleResult()得到查詢結果。例如:

Query query = entityManager.createQuery(
                    "select max(o.id) from Orders o");
Object result = query.getSingleResult();
Long max = (Long)result;
… …
having子句

Having 子句用于對 group by 分組設置約束條件,用法與where 子句基本相同,不同是 where 子句作用于基表或視圖,以便從中選擇滿足條件的記錄;having 子句則作用于分組,用于選擇滿足條件的組,其條件表達式中通常會使用聚合函數(shù)。
例如,以下語句用于查詢訂購總數(shù)大于100的商家所售商品及數(shù)量:

select o.seller, o.goodId, sum(o.amount) from V_Orders o group by 
o.seller, o.goodId having sum(o.amount) > 100

having子句與where子句一樣都可以使用參數(shù)。

關聯(lián)查詢

在JPQL中,很多時候都是通過在實體類中配置實體關聯(lián)的類屬性來實現(xiàn)隱含的關聯(lián)(join)查詢。例如:
select o from Orders o where o.address.streetNumber=2000
上述JPQL語句編譯成以下SQL時就會自動包含關聯(lián),默認為左關聯(lián)。
在某些情況下可能仍然需要對關聯(lián)做精確的控制。為此,JPQL 也支持和 SQL 中類似的關聯(lián)語法。如:
left out join / left join
inner join
left join / inner join fetch
其中,left join和left out join等義,都是允許符合條件的右邊表達式中的實體為空。

例如,以下外關聯(lián)查詢可以找出所有客戶實體記錄,即使它未曾訂貨: 
select c from Customers c left join c.orders o
以下內(nèi)關聯(lián)查詢只找出所有曾訂過商品的客戶實體記錄:
select c from Customers c inner join c.orders o
如果001號客戶下過5次訂單的話,以下fetch關聯(lián)查詢將得到 5個客戶實體的引用,并且執(zhí)行了 5 個訂單的查詢:
select c from Customers c left join fetch c.orders o where c.id=001
子查詢

JPQL也支持子查詢,在 where 或 having 子句中可以包含另一個查詢。當子查詢返回多于 1 個結果集時,它常出現(xiàn)在 any、all、exist s表達式中用于集合匹配查詢。它們的用法與SQL語句基本相同。


子查詢
JPQL函數(shù)

JPQL提供了以下一些內(nèi)建函數(shù),包括字符串處理函數(shù)、算術函數(shù)和日期函數(shù)。
字符串處理函數(shù)主要有:
concat(String s1, String s2):字符串合并/連接函數(shù)。
substring(String s, int start, int length):取字串函數(shù)。
trim([leading|trailing|both,] [char c,] String s):從字符串中去掉首/尾指定的字符或空格。
lower(String s):將字符串轉換成小寫形式。
upper(String s):將字符串轉換成大寫形式。
length(String s):求字符串的長度。
locate(String s1, String s2[, int start]):從第一個字符串中查找第二個字符串(子串)出現(xiàn)的位置。若未找到則返回0。
算術函數(shù)主要有 abs、mod、sqrt、size 等。Size 用于求集合的元素個數(shù)。
日期函數(shù)主要為三個,即 current_date、current_time、current_timestamp,它們不需要參數(shù),返回服務器上的當前日期、時間和時戳。

update語句

update語句用于執(zhí)行數(shù)據(jù)更新操作。主要用于針對單個實體類的批量更新
以下語句將帳戶余額不足萬元的客戶狀態(tài)設置為未償付:
update Customers c set c.status = '未償付' where c.balance < 10000

delete語句

delete語句用于執(zhí)行數(shù)據(jù)更新操作。
以下語句刪除不活躍的、沒有訂單的客戶:
delete from Customers c where c.status =
'inactive' and c.orders is empty

Spring 整合 JPA

三種整合方式:
LocalEntityManagerFactoryBean:適用于那些僅使用 JPA 進行數(shù)據(jù)訪問的項目,該 FactoryBean 將根據(jù)JPA PersistenceProvider 自動檢測配置文件進行工作,一般從“META-INF/persistence.xml”讀取配置信息,這種方式最簡單,但不能設置 Spring 中定義的DataSource,且不支持 Spring 管理的全局事務
從JNDI中獲?。河糜趶?Java EE 服務器獲取指定的EntityManagerFactory,這種方式在進行 Spring 事務管理時一般要使用 JTA 事務管理
LocalContainerEntityManagerFactoryBean:適用于所有環(huán)境的 FactoryBean,能全面控制 EntityManagerFactory 配置,如指定 Spring 定義的 DataSource 等等。

<!-- 配置 JPA 提供者的適配器 -->
<bean id="jpaVendorAdapter"     class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="databasePlatform">
        <bean class="com.atguigu.ssps.modules.persistence.Hibernates" 
            factory-method="getDialect">
                <constructor-arg ref="dataSource"></constructor-arg>
        </bean>
    </property>
</bean>
<!-- 配置 JPA 的 EntityManager -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter"></property>
    <property name="packagesToScan" value="com.atuigu.crm"></property>
    <property name="jpaProperties">
        <props>
            <!-- 二級緩存相關 -->
            <prop key="hibernate.cache.region.factory_class">
                org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
            <prop key="net.sf.ehcache.configurationResourceName">
                ehcache-hibernate.xml</prop>
            <!-- 生成的數(shù)據(jù)表的列的映射策略 -->
            <prop key="hibernate.ejb.naming_strategy">
                org.hibernate.cfg.ImprovedNamingStrategy</prop>
            <!-- hibernate 基本屬性 -->
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容