中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

廣州黃埔區(qū)網(wǎng)站建設(shè)北京seo網(wǎng)站優(yōu)化公司

廣州黃埔區(qū)網(wǎng)站建設(shè),北京seo網(wǎng)站優(yōu)化公司,北京做網(wǎng)站哪家專業(yè),天津門戶網(wǎng)站開發(fā)Hibernate EntityManager 專題 參考: JPA – EntityManager常用API詳解EntityManager基本概念 基本概念及獲得 EntityManager 對象 基本概念 在使用持久化工具的時候,一般都有一個對象來操作數(shù)據(jù)庫,在原生的Hibernate中叫做Session&…

Hibernate EntityManager 專題

參考:

  • JPA – EntityManager常用API詳解
  • EntityManager基本概念

基本概念及獲得 EntityManager 對象

基本概念

在使用持久化工具的時候,一般都有一個對象來操作數(shù)據(jù)庫,在原生的Hibernate中叫做Session,在 JPA 中叫做EntityManager,在MyBatis中叫做SqlSession,通過這個對象來操作數(shù)據(jù)庫。

EntityManager是 JPA 中用于增刪改查的接口,連接內(nèi)存中的 java 對象和數(shù)據(jù)庫的數(shù)據(jù)存儲。Hibernate EntityManager是圍繞提供JPA編程接口實現(xiàn)的Hibernate Core的一個包裝,支持JPA實體實例的生命周期,并允許用標(biāo)準(zhǔn)的Java Persistence查詢語言編寫查詢。

EntityManager稱為實體管理器,它由EntityManagerFactory所創(chuàng)建。EntityManagerFactory,作為EntityManager的工廠,包含有當(dāng)前O-R映射的元數(shù)據(jù)信息,每個EntityManagerFactory,可稱為一個持久化單元(PersistenceUnit),每個持久化單元可認(rèn)為是一個數(shù)據(jù)源的映射(所謂數(shù)據(jù)源,可理解為一個數(shù)據(jù)庫,可以在應(yīng)用服務(wù)器中配置多個數(shù)據(jù)源,同時使用不同的PersistenceUnit來映射這些數(shù)據(jù)源,從而能夠很方便的實現(xiàn)跨越多個數(shù)據(jù)庫之間的事務(wù)操作!)

PersistenceContext,稱為持久化上下文,它一般包含有當(dāng)前事務(wù)范圍內(nèi)的,被管理的實體對象(Entity)的數(shù)據(jù)。每個EntityManager,都會跟一個PersistenceContext相關(guān)聯(lián)。PersistenceContext中存儲的是實體對象的數(shù)據(jù),而關(guān)系數(shù)據(jù)庫中存儲的是記錄,EntityManager正是維護這種OR映射的中間者,它可以把數(shù)據(jù)從數(shù)據(jù)庫中加載到PersistenceContext中,也可以把數(shù)據(jù)從PersistenceContext中持久化到數(shù)據(jù)庫,EntityManager通過Persist、merge、remove、refresh、flush等操作來操縱PersistenceContext與數(shù)據(jù)庫數(shù)據(jù)之間的同步!

EntityManager是應(yīng)用程序操縱持久化數(shù)據(jù)的接口。它的作用與hibernate session類似。為了能夠在一個請求周期中使用同一個session對象,在hibernate的解決方案中,提出了currentSession的概念,hibernate中的current session,可以跟JTA事務(wù)綁定,也可以跟當(dāng)前線程綁定。在hibernate中,session管理著所有的持久化對象的數(shù)據(jù)。而在EJB3中,EntityManager管理著PersistenceContext,PersistenceContext正是被管理的持久化對象的集合。

在 Java EE 環(huán)境下,一個 JTA 事務(wù)通常會橫跨多個組件的調(diào)用(比如多個 EJB 組件的方法調(diào)用)。這些組件需要能夠在單個事務(wù)范圍內(nèi)訪問到同樣的PersistenceContext。為了滿足這種情況的需要,當(dāng)EntityManager被注入或通過 JNDI 被查詢的時候,它的 PersistenceContext 將會在當(dāng)前事務(wù)范圍內(nèi)自動傳播,引用到同一個 Persistence unit 的EntityManager將使用同樣的 PersistenceContext。這可以避免在不同的組件之間傳遞EntityManager引用。

通過容器來傳遞PersistenceContext,而不是應(yīng)用程序自己來傳遞EntityManager。這種方式(由容器管理著PersistenceContext,并負(fù)責(zé)傳遞到不同的EntityManager)稱為容器管理的實體管理器(Container-Managed EntityManager),它的生命周期由容器負(fù)責(zé)管理,編程人員不需要考慮EntityManger的連接,釋放以及復(fù)雜的事務(wù)問題等。

有一種不常見的情況是,應(yīng)用程序自身需要獨立訪問PersistenceContext。即每次創(chuàng)建一個EntityManager都會迫使創(chuàng)建一個新的PersistenceContext。這些PersistenceContext即使在同一個事務(wù)范圍內(nèi)也不會跟其它EntityManager共享!這個創(chuàng)建過程可以由EntityManagerFactory的createEntityManager方法來創(chuàng)建。這被稱為應(yīng)用管理的實體管理器(application-managed entity manager)。

獲得EntityManager對象

常用方式:SpringBoot容器托管對象方式:

依賴:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

對象注入:

@Autowired
private EntityManager entityManager;

實體狀態(tài)和轉(zhuǎn)換

在這里插入圖片描述


實體狀態(tài)詳解:

  • 臨時狀態(tài)

    實際上就是new了一個普通的 JavaBean 對象。

  • 托管狀態(tài)

    臨時狀態(tài)在調(diào)用 persist() 后,即可將一般的 JavaBean 做為了托管狀態(tài)的Bean,該Bean的任何屬性改動都會牽涉到數(shù)據(jù)庫記錄的改動。

    一旦該記錄flush到數(shù)據(jù)庫之后,并且事務(wù)提交了,那么此對象不在持久化上下文中,即:變?yōu)榱擞坞x(沒人管的孩子)狀態(tài)了。

    在游離狀態(tài)的時候調(diào)用更新、刷新方法后,游離狀態(tài)對象就變?yōu)榱嗽诔志没舷挛牡耐泄軤顟B(tài)了。

    通過管理器的find方法,將實體從數(shù)據(jù)庫查詢出來后,該實體也就變?yōu)榱送泄苄螒B(tài)。

  • 持久化狀態(tài)

    當(dāng)處在托管狀態(tài)的實體Bean被管理器flush了,那么就在極短暫的時間進入了持久化狀態(tài),事務(wù)提交之后,立刻變?yōu)榱擞坞x狀態(tài)。可以把持久化狀態(tài)當(dāng)做實實在在的數(shù)據(jù)庫記錄。

  • 游離狀態(tài)

    游離狀態(tài)就是提交到數(shù)據(jù)庫后,事務(wù)commit后實體的狀態(tài),因為事務(wù)已經(jīng)提交了,此時實體的屬性任你如何改變,也不會同步到數(shù)據(jù)庫,因為游離是沒人管的孩子,不在持久化上下文中。

  • 銷毀對象

    一般要刪除一個持久化對象的時候都是先find出來,之后調(diào)用remove方法刪之,此時這個對象就是銷毀對象,實際上就是瞬時對象的另一種形態(tài)罷了。


常用的 API

SELECT、DELETE

SELECT

? find() :返回指定的 OID 對應(yīng)的實體類對象,如果這個實體存在于當(dāng)前的持久化環(huán)境,則返回一個被緩存的對象;否則會創(chuàng)建一個新的 Entity, 并加載數(shù)據(jù)庫中相關(guān)信息;若 OID 不存在于數(shù)據(jù)庫中,則返回一個 null。

? getReference()

<T> T find(Class<T> entityClass, Object primaryKey);
<T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> var3);
<T> T find(Class<T> entityClass, Object primaryKey, LockModeType var3);
<T> T find(Class<T> entityClass, Object primaryKey, LockModeType var3, Map<String, Object> var4);<T> T getReference(Class<T> entityClass, Object primaryKey);// 參數(shù)說明:entityClass	// 被查詢的實體類類型primaryKey	// 待查找實體的主鍵值

異同:

  1. 當(dāng)在數(shù)據(jù)庫中沒有找到記錄時,find()方法會返回null,

    而getReference() 方法會拋出javax.persistence.EntityNotFoundException異常,

  2. 調(diào)用getReference()方法,返回的其實并不是實例對象,而是一個代理。當(dāng)你要使用實體時,才會真正的調(diào)用查詢語句來查詢實例對象

  3. 另外getReference()方法不保證 entity Bean已被初始化。

  4. 如果傳遞進getReference()或find()方法的參數(shù)不是實體Bean,都會引發(fā) IllegalArgumentException


DELETE

? Remove()

void remove(Object entity);
  1. 如果級聯(lián)關(guān)系cascade=CascadeType.ALL,在刪除person 時候,也會把級聯(lián)對象刪除。把cascade屬性設(shè)為cascade=CascadeType.REMOVE 有同樣的效果。

    Person person = em.find(Person.class, 2);
    em.remove (person);
    
  2. 如果傳遞進remove ()方法的參數(shù)不是實體Bean,會引發(fā)一個IllegalArgumentException

    remove()方法不能移除游離對象,只能移除持久化對象

    Order order = new Order();
    order.setId(140);
    entityManager.remove(order);
    

    上面這段代碼會拋出異常,因為order是自己創(chuàng)建的對象,也就是游離對象。必須這樣寫:

    Order order = new Order();
    order = entityManager.find(Order.class140);
    entityManager.remove(order);
    

    這段代碼中的order是從數(shù)據(jù)庫中獲取的,也就是持久化對象

    hibernate的delete()方法,只要對象有Id,就可以刪除


INSERT、UPDATE

INSERT

? persist(): 將臨時狀態(tài)的實體持久化到數(shù)據(jù)庫

void persist(Object entity);

persist方法:使對象由臨時狀態(tài)變?yōu)橥泄軤顟B(tài)。進而變?yōu)槌志没癄顟B(tài),就是執(zhí)行INSERT操作。

  1. 如果傳遞進persist()方法的參數(shù)不是實體Bean,會引發(fā)IllegalArgumentException
  2. 和hibernate的save()方法有些不同:當(dāng)Entity實體類中設(shè)置了主鍵自動生成時,如果傳入對象有id值,則會拋出異常

特殊場景及處理方案:

  • 特殊場景:Entity上使用自動生成ID值,但有些又需要插入的主鍵值是指定的ID值,而非自動生成的ID值

  • 處理方案1:Bean主鍵為Null,persist()后自動生成ID值,然后再使用QueryDsl-Jpa的update()方法,根據(jù)自動生成的ID值為條件,更新新增的實體的ID值為指定值

    @Test
    @Transactional
    @Rollback(false)
    public void addByEntityManager(){User bean = User.builder().addressee("孫六").build();entityManager.persist(u1);QUser entity = QUser.user;long execute = queryFactory.update(entity).set(entity.id, "11111").where(entity.id.eq(bean.getId())).execute();entityManager.flush();entityManager.clear();
    }
    
  • 處理方案2:使用Querydsl-SQL中,SqlQueryFactory.insert()方法。


UPDATE

? 當(dāng)實體正在被容器管理,即托管狀態(tài),你可以調(diào)用實體的set方法對數(shù)據(jù)進行修改,在容器決定flush時(這個由Container自行判斷),更新的數(shù)據(jù)才會同步到數(shù)據(jù)庫,而不是在調(diào)用了set方法對數(shù)據(jù)進行修改后馬上同步到數(shù)據(jù)庫。如果希望修改后的數(shù)據(jù)馬上同步到數(shù)據(jù)庫,可以調(diào)用 EntityManager.flush() 方法。

// 使用示例
@tranational
publicvoid updatePerson() {Person person = entityManager.find(Person.class, 1);person.setName("lihuoming");	//方法執(zhí)行完后即可更新數(shù)據(jù)entityManager.merge(person);
}

? Merge

<T> T merge(T entity);
  1. 傳入的對象沒有id

    在這種情況下,調(diào)用merge方法,將返回一個新的對象(有id),并對這個新的對象執(zhí)行insert操作。

  2. 傳入的對象有id,entityManager的緩存中沒有該對象,數(shù)據(jù)庫中沒有該記錄:

    在這種情況下,調(diào)用merge方法,將返回一個新的對象,并對該對象執(zhí)行insert操作。

    注意:如果Entity的主鍵設(shè)置的是自動生成,則新對象的id并不是原傳入對象的id,而是自動生成的(比如自增長的id)。(其實和情況1的結(jié)果是一樣的)

  3. 傳入的對象有id,entityManager的緩存沒有該對象,數(shù)據(jù)庫中有該記錄

    在這種情況下,調(diào)用merge方法,將會從數(shù)據(jù)庫中查詢對應(yīng)的記錄,生成新的對象,然后將傳入的對象復(fù)制到新的對象,最后執(zhí)行update操作。

    簡單來說,就是更新操作。

  4. 傳入的對象有id,entityManager的緩存有該對象

    在這種情況下,調(diào)用merge方法,JPA會把傳入的對象賦值到entityManager的緩存中的對象,然后對entityManager緩存中的對象執(zhí)行update操作。(和情況3的結(jié)果一樣)

總結(jié):執(zhí)行merge時,如果實體ID為空,則進行insert操作。 如果有ID則進行update操作。


flush()、clear()

flush()

將實體的改變立刻刷新到數(shù)據(jù)庫中

當(dāng)EntityManager對象在一個session bean 中使用時,它是和服務(wù)器的事務(wù)上下文綁定的。EntityManager 在服務(wù)器的事務(wù)提交時提交并且同步它的內(nèi)容。

在一個session bean 中,服務(wù)器的事務(wù)默認(rèn)地會在調(diào)用堆棧的最后提交(如:方法的返回)。

// 例子1:在方法返回時才提交事務(wù)
public void updatePerson(Person person) {try {Person person = em.find(Person.class, 2);person.setName("lihuoming");em.merge(person);//后面還有眾多修改操作} catch (Exception e) {e.printStackTrace();}//更新將會在這個方法的末尾被提交和刷新到數(shù)據(jù)庫中
}

默認(rèn)只在當(dāng)事務(wù)提交時才將改變更新到數(shù)據(jù)庫中,容器將所有數(shù)據(jù)庫操作集中到一個批處理中,這樣就減少了代價昂貴的與數(shù)據(jù)庫的交互。

當(dāng)調(diào)用 persist( ),merge( )或 remove( ) 這些方法時,更新并不會立刻同步到數(shù)據(jù)庫中,直到容器決定刷新到數(shù)據(jù)庫中時才會執(zhí)行,默認(rèn)情況下,容器決定刷新是在 “相關(guān)查詢” 執(zhí)行前或事務(wù)提交時發(fā)生。

當(dāng)然 “相關(guān)查詢” 除 find() 和 getreference() 之外,這兩個方法是不會引起容器觸發(fā)刷新動作的,默認(rèn)的刷新模式是可以改變的。


如果你需要在事務(wù)提交之前將更新刷新到數(shù)據(jù)庫中,你可以直接地調(diào)用EntityManager.flush()方法。

ORM框架執(zhí)行的一些更新數(shù)據(jù)庫的方法,其實質(zhì)是在更新緩存,只有調(diào)用了 flush() 后才會將緩存同步到數(shù)據(jù)庫,即真正執(zhí)行SQL語句,但是這時并沒有真正將數(shù)據(jù)保存進數(shù)據(jù)庫,需要事務(wù)commit后才能全部保存。一般 flush 后立刻就會進行事務(wù)的提交。

public void updatePerson(Person person) {try {Person person = em.find(Person.class, 2);person.setName("lihuoming");em.merge(person);em.flush();//手動將更新立刻刷新進數(shù)據(jù)庫//后面還有眾多修改操作} catch (Exception e) {e.printStackTrace();}
}

clear()

分離所有當(dāng)前正在被管理的實體

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

2.在處理大量實體的時候,如果你不把已經(jīng)處理過的實體從EntityManager中分離出來,將會消耗你大量的內(nèi)存。

3.調(diào)用EntityManager 的clear()方法后,所有正在被管理的實體將會從持久化內(nèi)容中分離出來。

4.有一點需要說明下,在事務(wù)沒有提交前(事務(wù)默認(rèn)在調(diào)用堆棧的最后提交,如:方法的返回),如果調(diào)用clear()方法,之前對實體所作的任何改變將會丟失,所以建議在調(diào)用clear()方法之前先調(diào)用flush()方法保存更改。


JcreateQuery() – PQL

創(chuàng)建查詢對象

除了使用 find() 或 getReference() 方法來獲得Entity Bean之外,你還可以通過 JPQL 得到實體Bean。要執(zhí)行 JPQL 語句,你必須通過 EntityManager 的 createQuery() 或 createNamedQuery() 方法創(chuàng)建一個Query 對象。

注:JPQL 沒有插入語句。即不能執(zhí)行insert語句。


? getResultList()

Query query = em.createQuery("select p from Person p where p.name=’黎明’");
List result = query.getResultList();Iterator iterator = result.iterator();
while( iterator.hasNext() ){
//處理Person
}

? getSingleResult()

返回查詢的第一條數(shù)據(jù),可以進行強轉(zhuǎn),如:

// 查詢數(shù)目:
Query query = em.createQuery("select count(1) from Person p");
Long num = (Long)query. getSingleResult ();// 強轉(zhuǎn)為實體:
Query query = em.createQuery("select p from Person p");
User user = (User)query. getSingleResult ();

? executeUpdate()

// 執(zhí)行更新和刪除操作,返回受影響的記錄數(shù)。
Query query = em.createQuery("delete from Person");
int result =query.executeUpdate();	 //影響的記錄數(shù)

? 關(guān)于 **JPQL 和SQL **中參數(shù)的問題:

  1.  使用標(biāo)識符
    
Query query =em.createQuery("delete from Person p where p.name := name");
query.setParameter("name","張三");
int result =query.executeUpdate(); //影響的記錄數(shù)
  1.  使用索引下標(biāo)
    
Query query =em.createQuery("delete from Person p where p.id = ?1 ");
query.setParameter(1, "張三");
int result =query.executeUpdate(); //影響的記錄數(shù)  

createNaiveQuery() – SQL

用法基本同createQuery(),只不過這里使用的不是 JPQL 而是SQL

? 將查詢到的數(shù)據(jù)映射成實體:

Query query = em.createNativeQuery("select * from person", Person.class);
List result = query.getResultList();if (result != null){Iterator iterator = result.iterator();while( iterator.hasNext() ){Person person= (Person)iterator.next();}
}

refresh()

如果懷疑當(dāng)前被管理的實體已經(jīng)不是數(shù)據(jù)庫中最新的數(shù)據(jù),則可以通過 refresh() 方法刷新實體,容器會把數(shù)據(jù)庫中的新值重寫進實體。這種情況一般發(fā)生在獲取了實體之后,有人更新了數(shù)據(jù)庫中的記錄,這時需要得到最新的數(shù)據(jù)。當(dāng)然再次調(diào)用 find() 或 getReference() 方法也可以得到最新數(shù)據(jù),但這種做法并不優(yōu)雅。

User user = em.find(User.class, 1);//第二次同樣的查詢不會訪問數(shù)據(jù)庫
user = em.find(User.class, 1);// 運行以上代碼,發(fā)現(xiàn)調(diào)用了兩次find,但是只執(zhí)行了一次select語句,這是緩存導(dǎo)致的。// 執(zhí)行refresh()方法刷新緩存,容器會把數(shù)據(jù)庫中的新值重寫進實體。
User user = em.find(User.class, 1);
em.refresh(user);

其他方法

contains()

判斷實體是否還在EntityManage的管理下,或者說是否屬于當(dāng)前持久上下文環(huán)境。

contains() 方法使用一個實體作為參數(shù),如果這個實體對象當(dāng)前正被持久化內(nèi)容管理,返回值為true,否則為false。

如果傳遞的參數(shù)不是實體 Bean,將會引發(fā)一個IllegalArgumentException.

User user = em.find(User.class, 1);if (em.contains(user)){//正在被持久化內(nèi)容管理
}else{//已經(jīng)不受持久化內(nèi)容管理
}

getFlushMode ():

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


setFlushMode()

改變實體管理器的Flush模式

setFlushMode()的Flush模式有2種類型:AUTO 和 COMMIT。AUTO為默認(rèn)模式。

// 改變實體管理器的Flush模式
em.setFlushMode(FlushModeType.COMMIT);
  • FlushModeType.AUTO

    默認(rèn)情況下除了在事務(wù)提交時 flush,在進行查詢時(除了 find() 和 getreference() 查詢)也會進行一次 flush ,比如使用JPQL查詢前會進行一次flush。

    使用場合:在大量更新數(shù)據(jù)的過程中沒有任何查詢語句(除了 find() 和 getreference() 查詢)的執(zhí)行。

  • FlushModeType.COMMIT

    刷新只有在事務(wù)提交時才發(fā)生,查詢不觸發(fā)。

    使用場合:在大量更新數(shù)據(jù)的過程中存在查詢語句(除了find() 和 getreference() 查詢)的執(zhí)行。

其實上面兩種模式最終反映的結(jié)果是:JDBC 驅(qū)動跟數(shù)據(jù)庫交互的次數(shù)。

JDBC 性能最大的增進是減少JDBC 驅(qū)動與數(shù)據(jù)庫之間的網(wǎng)絡(luò)通訊。

FlushModeType.COMMIT 模式使更新只在一次的網(wǎng)絡(luò)交互中完成,而 FlushModeType.AUTO 模式可能需要多次交互(觸發(fā)了多少次Flush 就產(chǎn)生了多少次網(wǎng)絡(luò)交互)


isOpen()

判斷當(dāng)前的實體管理器是否是打開狀態(tài)


close()

關(guān)閉實體管理器。

之后若調(diào)用實體管理器實例的方法或其派生的查詢對象的方法都將拋出 IllegalstateException 異常,除了 getTransaction 和 isOpen方法(返回 false)。

不過,當(dāng)與實體管理器關(guān)聯(lián)的事務(wù)處于活動狀態(tài)時,調(diào)用 close() 方法后持久上下文將仍處于被管理狀態(tài),直到事務(wù)完成。


getTransaction()

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


EntityTransaction 接口用來管理資源層實體管理器的事務(wù)操作

通過調(diào)用實體管理器的getTransaction方法 獲得其實例。

① begin ()

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

② commit ()

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

③ rollback ()

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

④ setRollbackOnly ()

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

⑤ getRollbackOnly ()

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

⑥ isActive ()

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

需要注意的是:

// 在JPA里面,先需要 getTransaction,再 begin 
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();// 在 hibernate 里面呢,直接 begin,然后進行 commit 
EntityTransaction transaction = session.beginTransaction();
transaction.commit();

JPA 調(diào)用存儲過程

參考:https://www.cnblogs.com/zhuang229/p/12227938.html

定義存儲過程及調(diào)用方式

定義一個簡單的存儲過程

傳入一個int參數(shù),返回這個參數(shù)+1

CREATE DEFINER=`root`@`localhost` PROCEDURE `plus1inout`(IN ARG INT, OUT res INT)
BEGIN SET res = ARG + 1;
END

注意:

  1. IN參數(shù)個數(shù)沒有限制。

  2. 如果out參數(shù)類型為sys_refcursor,那么最好只定義這 一個out參數(shù)(JPA API限制);

    sys_refcursor 類型的 out 參數(shù),在 JPA 中統(tǒng)一注冊為 Void.class 類型,參數(shù)模式定義為 ParameterMode.REF_CURSOR;

    使用getResultList()方法獲取游標(biāo)fetch到的多行數(shù)據(jù),返回結(jié)果為List<Object[]>,一個Object[]對應(yīng)一行數(shù)據(jù)。

  3. 如果使用Oracle 存儲包,只需在定義存儲過程名字時加個對應(yīng)的package名前綴即可(例如:包名.存儲過程名)。


JPA調(diào)用存儲過程的兩種方式

  • 基于Entity實體類,在實體類上使用@NamedStoredProcedureQuery注解(需要數(shù)據(jù)庫中有對應(yīng)的表,可自動映射結(jié)果集)
    • EntityManager創(chuàng)建createNamedStoredProcedureQuery,傳參調(diào)用
    • SpringDataJpa中Repository自定義方法,傳參調(diào)用
  • 直接使用EntityManager進行自定義(不需要數(shù)據(jù)庫中有對應(yīng)的表,需要自己處理結(jié)果集)
    • EntityManager創(chuàng)建StoredProcedureQuery對象,注冊 IN/OUT 參數(shù)模式

實體類(使用注解聲明存儲過程)

@NamedStoredProcedureQuery注解(解析詳見注解目錄)

  • name為唯一名稱,調(diào)用時使用;procedureName 為存儲過程名;

  • @Entity注解必須有

  • @Entity要求必須有主鍵id屬性(存儲過程可返回id任意值即可)

  • @Entity要求必須對應(yīng)數(shù)據(jù)庫表必須存在(JPA表檢查用)(若用EntityManager調(diào)用存儲過程,此條存疑)

import lombok.Data;
import javax.persistence.*;@Data
@Entity
// 存儲過程使用了注解@NamedStoredProcedureQuery,并綁定到一個隨意一個JPA表
@NamedStoredProcedureQueries({@NamedStoredProcedureQuery(name = "User.plus1", procedureName = "plus1inout", parameters = {@StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class),@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class) }),@NamedStoredProcedureQuery(name = "User.mytest", procedureName = "mytest") })
class user{@Idprivate Integer id;private String name;private String age;
}

EntityManager直接調(diào)用存儲過程

@Autowired
private EntityManager em;@Test
public void test01(){StoredProcedureQuery query = em.createStoredProcedureQuery("plus1inout")	// 創(chuàng)建StoredProcedureQuery對象,傳入被調(diào)用的存儲過程名稱.registerStoredProcedureParameter("ARG", Integer.class, ParameterMode.IN)	// 注冊參數(shù).registerStoredProcedureParameter("res", Integer.class, ParameterMode.OUT).setParameter("ARG", 20);	// 傳參query.execute();	// 執(zhí)行存儲過程調(diào)用String result = query.getOutputParameterValue("res").toString();	// 獲取存儲過程中的返回值System.out.println(result);
}

調(diào)用基于實體類注解的存儲過程

使用EntityManager調(diào)用基于Entity實體類注解的存儲過程。實體類詳見 JPA調(diào)用存儲過程

@Autowired
private EntityManager em;@Test
public void test02(){StoredProcedureQuery query = em// 創(chuàng)建NamedStoredProcedureQuery對象,傳入實體類上@NamedStoredProcedureQuery注解中name的值.createNamedStoredProcedureQuery("proKQAttendanceRecord")// IN模式的參數(shù)可以在實體類上注解,此處相應(yīng)注釋掉// .registerStoredProcedureParameter("PRM_ID", Integer.class, ParameterMode.IN)// 使用EntityManager調(diào)用基于Entity實體類注解的存儲過程時,OUT或INOUT模式的參數(shù),必須要在此處注冊,并刪掉原實體類上相應(yīng)的參數(shù)注解。不然運行報錯。.registerStoredProcedureParameter("PRM_APPCODE", Integer.class, ParameterMode.OUT).registerStoredProcedureParameter("PRM_ERRMSGE", Integer.class, ParameterMode.OUT).setParameter("PRM_ID", attId);		// 傳參query.execute();List resultList = query.getResultList();Object code = query.getOutputParameterValue("PRM_APPCODE");Object msg = query.getOutputParameterValue("PRM_ERRMSGE");
}
http://www.risenshineclean.com/news/54759.html

相關(guān)文章:

  • 做網(wǎng)站郴州百度信息流效果怎么樣
  • 涪城移動網(wǎng)站建設(shè)免費推廣網(wǎng)站注冊入口
  • 做自己的購物網(wǎng)站網(wǎng)站推廣要點
  • 日照手機網(wǎng)站設(shè)計小學(xué)生抄寫新聞20字
  • 河南做網(wǎng)站公司排名sem代運營托管公司
  • 微信高端網(wǎng)站建設(shè)百度愛采購平臺官網(wǎng)
  • 徐州企業(yè)網(wǎng)站排名優(yōu)化官網(wǎng)百度
  • 深圳品牌模板網(wǎng)站建設(shè)百度推廣助手怎么用
  • 扁平化 手機網(wǎng)站首頁5118大數(shù)據(jù)平臺官網(wǎng)
  • wordpress固定鏈自定義結(jié)構(gòu)企業(yè)關(guān)鍵詞優(yōu)化最新報價
  • 公司個人怎么做網(wǎng)絡(luò)推廣seo建站工具
  • 青島做網(wǎng)站方案網(wǎng)上營銷培訓(xùn)課程
  • 蕪湖做網(wǎng)站哪家好網(wǎng)站流量分析工具
  • 怎么在國外網(wǎng)站做推廣百度推廣的幾種方式
  • 重慶江北區(qū)網(wǎng)站建設(shè)公司seo網(wǎng)絡(luò)推廣是什么意思
  • 個人網(wǎng)站做公司網(wǎng)站企業(yè)網(wǎng)絡(luò)營銷案例
  • 秦皇島海三建設(shè)沒錢了奉化seo頁面優(yōu)化外包
  • wordpress做物流網(wǎng)站百度搜索引擎的特點
  • 給人做網(wǎng)站多少錢張掖seo
  • 濰坊地區(qū)網(wǎng)站制作免費輿情監(jiān)測平臺
  • wordpress 文章推薦一篇福建優(yōu)化seo
  • 網(wǎng)站建設(shè)的目的和作用網(wǎng)站seo推廣排名
  • 阿里云企業(yè)網(wǎng)站怎么收費百度競價排名多少錢
  • 網(wǎng)站建設(shè)調(diào)查報告范文seo是怎么優(yōu)化上去
  • 找人做網(wǎng)站做的很爛seo診斷服務(wù)
  • 網(wǎng)站運營托管協(xié)議杭州網(wǎng)絡(luò)優(yōu)化公司排名
  • 武漢做網(wǎng)站的公司有哪些比較好友情鏈接也稱為
  • 糧食局網(wǎng)站建設(shè)報告網(wǎng)紅推廣
  • 清遠黨風(fēng)廉政建設(shè)網(wǎng)站不受限制的搜索瀏覽器
  • 做網(wǎng)站每年要交不費用嗎石家莊seo公司