ORM規(guī)范

JPA 概述

JPA 介紹

JPA 本質(zhì)上就是一種 ORM 規(guī)范,不是 ORM 框架,因為 JPA 并未提供 ORM 實(shí)現(xiàn),它只是制定了一套規(guī)范,提供了一些接口,具體實(shí)現(xiàn)由 ORM 廠商決定。

目前成都創(chuàng)新互聯(lián)已為數(shù)千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管成都網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計、岐山網(wǎng)站維護(hù)等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

JPA 包括三方面的技術(shù)

ORM 映射元數(shù)據(jù)

JPA API

查詢語言(JPQL)

使用 JPA 持久化對象的步驟

創(chuàng)建 EntityMangerFactory

通過 EntityManagerFactory 獲得 EntityManager 實(shí)例

開始事務(wù)

執(zhí)行持久化操作

提交事務(wù)

關(guān)閉 EntityManager

關(guān)閉 EntityManagerFactory

// 創(chuàng)建 EntityManageFactory
String persistenceUnitName = "NewPersistenceUnit";
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
// 創(chuàng)建 EntityManage
EntityManager entityManager = entityManagerFactory.createEntityManager();
// 開始事務(wù)
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
// 執(zhí)行持久化操作
Customer customer = new Customer();
customer.setAge(12);
customer.setEmail("tom@163.com");
customer.setLastName("tom");
entityManager.persist(customer);
// 提交事務(wù)
transaction.commit();
// 關(guān)閉 EntityManage
entityManager.close();
// 關(guān)閉 EntityManageFactory
entityManagerFactory.close();

persistence.xml

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

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="NewPersistenceUnit">
        <!--配置將使用哪個產(chǎn)品作為實(shí)現(xiàn)-->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <!--添加持久化類-->
        <class>com.kernel.jpa.helloworld.Customer</class>
        <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="123456"/>
            <!--配置hibernate的基本屬性-->
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>

JPA 的基本注解

@Entity

標(biāo)記一個類為實(shí)體類,添加該注解后,會在數(shù)據(jù)庫中創(chuàng)建一個和類名相同的表。

@Transient

使用該注解忽略工具方法,不需要映射為數(shù)據(jù)表的一列。

@Temporal

設(shè)置 Date 類型的精度。

DATE:精確到年月日

TIME:精確到時分秒

TIMESTAMP:精確到年月日時分秒

@Table

當(dāng)實(shí)體類與其映射的數(shù)據(jù)表名稱不一致時,需要使用該注解標(biāo)注,該注解與 @Entity 標(biāo)注并列使用,置于實(shí)體類注解之前。

name:數(shù)據(jù)庫的表名

catalog:數(shù)據(jù)庫目錄

schema:數(shù)據(jù)庫模式

@ID

該注解聲明一個實(shí)體類的屬性映射為數(shù)據(jù)庫的主鍵,一般我們將其標(biāo)注在 getter 方法上。

@GeneratedValue

該注解用來設(shè)置主鍵的生成策略,通過 strategy 屬性指定

有四種策略:

IDENTITY:采用數(shù)據(jù)庫 ID 自增長的方式來自增主鍵字段,Oracle 不支持。

AUTO:JPA 自動選擇合適的策略,默認(rèn)選項。

SEQUENCE:通過序列產(chǎn)生主鍵,通過 @SequenceGenerator 注解指定序列名,MySQL 不支持。

TABLE:通過表產(chǎn)生主鍵,框架借由表模擬序列產(chǎn)生主鍵,使用該策略可以使應(yīng)用更易于數(shù)據(jù)庫移植。

@Cloumn

當(dāng)實(shí)體類的屬性與其映射的數(shù)據(jù)表的列不同名時需要標(biāo)注該注解。

name:數(shù)據(jù)表的列名。

unique:唯一約束。

nullable:是否可以為空。

length:列的長度。

columnDefinition

@Basic

表示基本注解,默認(rèn)為沒有標(biāo)注任何注解的 getter 方法添加該注解。

JPA API

Persistence

該類包含一個名為 createEntityManagerFactory 的 靜態(tài)方法 ,用來獲取 EntityManagerFactory。

EntityManagerFactory

EntityManagerFactory 接口主要用來創(chuàng)建 EntityManager 實(shí)例,提供了四個方法:

createManagerFactory() 用來創(chuàng)建 EntityManager。

createManagerFactory(Map map) Map 參數(shù)用來提供 EntityManager 的屬性。

isOpen() 檢查 EntityManagerFactory 是否處于打開狀態(tài)。

close() 關(guān)閉 EntityManagerFactory。

EntityManager

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

實(shí)體的狀態(tài):

新建狀態(tài):新創(chuàng)建的對象,尚未擁有持久化主鍵。

持久化狀態(tài):已經(jīng)擁有持久化主鍵并和持久化建立了上下文環(huán)境。

游離狀態(tài):已經(jīng)擁有了持久化主鍵但是沒有和持久化建立上下文環(huán)境。

刪除狀態(tài):已經(jīng)擁有了持久化主鍵并和持久化建立了上下文環(huán)境,但是從數(shù)據(jù)庫中被刪除。

find(Class<T> entityClass, Object primayKey) 返回指定主鍵對應(yīng)的實(shí)體類,如果這個實(shí)體存在與當(dāng)前的持久化環(huán)境,則返回的是一個緩存對象,否則,會創(chuàng)建一個新的實(shí)體對象,如果沒有找到,返回 null。

getReference (Class<T> entityClass,Object primaryKey) 和 find 類似,只不過如果緩存中不存在當(dāng)前實(shí)體,會創(chuàng)建一個實(shí)體類代理,但是不會立即加載數(shù)據(jù)庫中的信息,只有第一次使用時,才會加載信息,如果找不到對應(yīng)的實(shí)體,拋出 EntityNotFoundException。

persist (Object entity):將創(chuàng)建的實(shí)體對象變成持久化狀態(tài)。

remove (Object entity):刪除實(shí)例。

merge (T entity):數(shù)據(jù)庫的插入和更新操作:

如果傳入的對象是一個臨時對象,即沒有 id 的對象,JPA 創(chuàng)建一個新的對象,并復(fù)制臨時對象的屬性到新對象中,將新對象執(zhí)行持久化操作。

如果傳入的對象是一個游離對象,即存在 id 的對象,首先查詢緩存中是否存在 id 對象的持久化對象,如果存在,將游離對象的屬性拷貝到新創(chuàng)建的對象中,并執(zhí)行更新操作;如果不存在,就查詢數(shù)據(jù)庫中是否存在 id 對應(yīng)的記錄,如果存在,將游離對象的屬性拷貝到新創(chuàng)建的對象中,并執(zhí)行更新操作;如果不存在,JPA 創(chuàng)建一個新的對象,并復(fù)制臨時對象的屬性到新對象中,將新對象執(zhí)行持久化操作。

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

setFulshMode(FlushModeType flushMode):設(shè)置持久化上下文的 Flush 模式:

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

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

getFlushMode() 獲取持久化上文的 Flush 模式。

refresh() 用數(shù)據(jù)庫實(shí)體記錄的值更新實(shí)體對象的狀態(tài)。

clear() 清除持久化上下文環(huán)境,斷開所有關(guān)聯(lián)的實(shí)體。

contains() 判斷一個實(shí)例是否屬于當(dāng)前持久化上下文環(huán)境管理的實(shí)體。

isOpen() 查詢 EntityManager 是否處于打開狀態(tài)

getTransaction() 獲得一個事務(wù)。

close() 關(guān)閉 EntityManager 實(shí)例。

EntityTransaction

begin() 開啟事務(wù)。

commit() 提交事務(wù)。

rollback() 回滾事務(wù)。

setRollbackOnly() 使當(dāng)前事務(wù)只能被撤消。

getRollbackOnly() 查看當(dāng)前事務(wù)是否設(shè)置了只能撤消標(biāo)志。

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

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

映射雙向一對多及多對一的關(guān)聯(lián)關(guān)系

雙向一對多關(guān)系中,必須存在一個關(guān)系維護(hù)端,在 JPA 規(guī)范中,要求 many 的一方作為關(guān)系的維護(hù)端(owner side),one 的一方作為被維護(hù)端(inverse side)。
可以在 one 方指定 @OneToMany 注釋并設(shè)置 mappedBy 屬性,以指定它是這一關(guān)聯(lián)中的被維護(hù)端,many 為維護(hù)端。
在 many 方指定 @ManyToOne 注釋,并使用 @JoinColumn 指定外鍵名稱。

使用 mappedBy 設(shè)置維護(hù)段的字段。

映射雙向一對一的關(guān)聯(lián)關(guān)系

基于外鍵的 1-1 關(guān)聯(lián)關(guān)系:在雙向的一對一關(guān)聯(lián)中,需要在關(guān)系被維護(hù)端(inverse side)中的 @OneToOne 注釋中指定 mappedBy,以指定是這一關(guān)聯(lián)中的被維護(hù)端。同時需要在關(guān)系維護(hù)端(owner side)建立外鍵列指向關(guān)系被維護(hù)端的主鍵列。

在維護(hù)端設(shè)置 unique 設(shè)置為 true。

如果延遲加載要起作用, 就必須設(shè)置一個代理對象。
Manager 其實(shí)可以不關(guān)聯(lián)一個 Department。
如果有 Department 關(guān)聯(lián)就設(shè)置為代理對象而延遲加載,如果不存在關(guān)聯(lián)的 Department 就設(shè)置 null,因為外鍵字段是定義在 Department 表中的,Hibernate 在不讀取 Department 表的情況是無法判斷是否有關(guān)聯(lián)有 Deparmtment,因此無法判斷設(shè)置 null 還是代理對象,而統(tǒng)一設(shè)置為代理對象,也無法滿足不關(guān)聯(lián)的情況,所以無法使用延遲加載,只有顯式讀取 Department。

映射雙向多對多的關(guān)聯(lián)關(guān)系

在雙向多對多關(guān)系中,我們必須指定一個關(guān)系維護(hù)端(owner side),可以通過 @ManyToMany 注釋中指定 mappedBy 屬性來標(biāo)識其為關(guān)系維護(hù)端。

@ManyToMany@JoinTable(name="中間表名稱",
br/>@JoinTable(name="中間表名稱",
inversejoinColumns=@JoinColumn(name="對方類的外鍵",
br/>referencedColumnName="本類與外鍵對應(yīng)的主鍵"),
inversejoinColumns=@JoinColumn(name="對方類的外鍵",
)

使用二級緩存

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

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <persistence-unit name="NewPersistenceUnit">
        <!--配置將使用哪個產(chǎn)品作為實(shí)現(xiàn)-->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <!--添加持久化類-->
        <class>com.kernel.jpa.helloworld.Customer</class>
        <class>com.kernel.jpa.helloworld.Order</class>
        <class>com.kernel.jpa.helloworld.Manager</class>
        <class>com.kernel.jpa.helloworld.Department</class>
        <!--配置二級緩存的策略-->
        <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="123456"/>
            <!--配置hibernate的基本屬性-->
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <!--二級緩存相關(guān)-->
            <property name="hibernate.cache.use_second_level_cache" value="true"/>
            <property name="hibernate.cache.region.factory_class" value="EnCacheRegionFactory"/>
            <property name="hibernate.cache.use_query_cache" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

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ù)庫查詢的相關(guān)方法。調(diào)用 EntityManager 的 createQuery、create NamedQuery 及 createNativeQuery 方法可以獲得查詢對象,進(jìn)而可調(diào)用 Query 接口的相關(guān)方法來執(zhí)行查詢操作。

Query接口的主要方法:
int executeUpdate() 用于執(zhí)行update或delete語句。
List getResultList() 用于執(zhí)行select語句并返回結(jié)果集實(shí)體列表。
Object getSingleResult() 用于執(zhí)行只返回單個結(jié)果實(shí)體的select語句。
Query setFirstResult(int startPosition) 用于設(shè)置從哪個實(shí)體記錄開始返回查詢結(jié)果。
Query setMaxResults(int maxResult) 用于設(shè)置返回結(jié)果實(shí)體的最大數(shù)。與setFirstResult結(jié)合使用可實(shí)現(xiàn)分頁查詢。
Query setFlushMode(FlushModeType flushMode) 設(shè)置查詢對象的Flush模式。參數(shù)可以取2個枚舉值:FlushModeType.AUTO 為自動更新數(shù)據(jù)庫記錄,F(xiàn)lushMode Type.COMMIT 為直到提交事務(wù)時才更新數(shù)據(jù)庫記錄。

使用 Hibernate 的查詢緩存

String jpql = "FROM Customer c WHERE c.age > ?";
// 設(shè)置查詢緩存
Query query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);
// 占位符的索引從1開始
query.setParameter(1, 2);
List<Customer> resultList = query.getResultList();
resultList = query.getResultList();

關(guān)聯(lián)查詢

JPQL 也支持和 SQL 中類似的關(guān)聯(lián)語法。如:
left out join / left join
inner join
left join / inner join fetch
其中,left join和left out join等義,都是允許符合條件的右邊表達(dá)式中的實(shí)體為空。

子查詢和 JPQL 函數(shù)

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

JPQL提供了以下一些內(nèi)建函數(shù),包括字符串處理函數(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):將字符串轉(zhuǎn)換成小寫形式。
upper(String s):將字符串轉(zhuǎn)換成大寫形式。
length(String s):求字符串的長度。
locate(String s1, String s2[, int start]):從第一個字符串中查找第二個字符串(子串)出現(xiàn)的位置。若未找到則返回0。

整合 Spring

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

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--配置自動掃描的包-->
    <context:component-scan base-package="com.kernel.spring.jpa"/>
    <!--配置C3P0數(shù)據(jù)源-->
    <context:property-placeholder location="classpath:db.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
        <property name="user" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--配置EntityManagerFactory-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--配置JPA適配器-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <!--配置實(shí)體類所在的包-->
        <property name="packagesToScan" value="com.kernel.spring.jpa.entities"/>
        <!--配置JPA的基本屬性-->
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>
    <!--配置JPA使用的事務(wù)管理器-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!--配置基于注解的事務(wù)配置-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

當(dāng)前題目:ORM規(guī)范
網(wǎng)站網(wǎng)址:http://muchs.cn/article12/pjpddc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、網(wǎng)站改版、網(wǎng)站內(nèi)鏈、域名注冊、靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)