一、jpa是什么
JPA:java persistence API java持久化API,是一種ORM規(guī)范,由廠商來實現(xiàn),目前有HB,OpenJPA,TopLink和? EclipseJPA。
二、spring集成JPA
1.JPA一共兩種配置類型:應(yīng)用程序驅(qū)動(管理)和容器驅(qū)動(管理)
1)兩種類型都需要獲取的EntityManagerFactory,然后來訪問數(shù)據(jù)庫。
2)區(qū)別在于,
a.應(yīng)用程序管理類型是基于配置文件的,persisitence.xml,在這個配置文件中,配置n個持久化單元和數(shù)據(jù)庫屬性配置,請求到達(dá)后,由程序去解析文件來配置和創(chuàng)建這個持久化單元,至于事物需要應(yīng)用程序本身來控制,集成到spring之后,獲取factory和事物由spring容器來控制,但是配置文件仍是必須的。
b.根據(jù)上述應(yīng)用程序管理的配置,可以看出來,至少需要一個配置,并且每次請求到達(dá)后,由程序來初始化。而容器管理器,依托于spring容器時,在初始化的時候,直接根據(jù)配置信息初始化相關(guān)bean,生成所需要的factory。這種配置信息可以放到xml文件里,也可以使用代碼的方式,比如下面:
@Bean
public xxxxxxx? xxx(){
.....}
2.由于上述觀點,主要研究一下基于容器管理的JPA
1)LocalContainerEntityManagerFactory 此為構(gòu)造容器JPA的主要bean,也是要在初始化spring容器時需要注入到spring容器中的。
他支持幾個平時常用的方法,eg:
a.? setDataSource(dataSource)? 參數(shù)就是你的數(shù)據(jù)源,你可以自定義數(shù)據(jù)源,可以在xml里,也可以用@bean的方式注入。
b.? setJpaVendorAdapter(vendorAdapter) 標(biāo)注廠商類型,因為JPA只是一種規(guī)范,剛開始提到的(這個adapter可以自己實現(xiàn),具體的就不細(xì)說了)。
c.? setPackagesToScan(String[]) 掃描指定包路徑下的所有被@Entity表示的bean
以上只是一部分,因為這個類有個抽象父類。
3.還有jndi的方式。
上面只是代表我們已經(jīng)集成了JPA規(guī)范,啟動spring 容器后,容器中有我們可用的factory,下面是如何使用。
4.在service類中,注入以下其中之一的bean
1)?
????@PersisitenceUnit
????private EntityManagerFactory emf;
使用:emf.createEntityManager.xxxx
2)
????@PersistenceContext
????private EntityManager em;
使用:em.xxxxx;
第一種是直接講factory注入到service中,調(diào)用創(chuàng)建manager的方法之后執(zhí)行 數(shù)據(jù)庫操作。
EntityManager接口中具體的方法,還需要參照EntityManager.class中的
5.我們可以用spring data jpa 來封裝 和豐富dao層的這些api,因為spring會在運行時期自己查找匹配類和分解方法簽名
eg:findUserByIdOrNameOrderByNoAllIgnoringCase(Long id) spring會自定解析 之后動態(tài)生成子類,find為動詞,動詞是spring指定的幾個,比如,get read find count。
user為查找的對象,可以省略,下面再說為何可以省略,by 連接詞 后面跟條件,Or sql中的意思,OrderBy排序,AllIgnoringCase忽略大小寫。
這樣,根據(jù)約定來編寫方法簽名的接口即可動態(tài)生成子類。
這個接口如果寫的,前面說到查找對象為何可以省略呢,在這
public interface S implements JpaRepository 泛型中,User為目標(biāo)對象類型,Long 為主鍵類型。
6.其實寫到這,ORM的DAO層就已經(jīng)結(jié)束了,但是我們知道,基本的dao方法加上上面說的根據(jù)自定義方法簽名來生成方法 有很多時候并不符合我們的業(yè)務(wù)邏輯,比如簡單的,兩個表連接查詢。這個時候,spring data為我們提供了另一個方便:
public interface Op{
List search();
}
public interface S implements JpaRepository ,Op{
}
Op接口實現(xiàn)類,自定義自己的方法體,但是這個實現(xiàn)類的命名一定要以上面接口名稱為前綴,以「iml」為后綴
public class Siml implements Op{
public List search(){
..............;
}
}
這樣,容器在掃描時,會自動去匹配實現(xiàn)某接口的,以xx為前綴 以iml為后綴,將動態(tài)生成的實現(xiàn)類與這個實現(xiàn)類組合成一個類,在使用時直接注入
@Service
private Op siml;即可