Hibernate JPA 快速入門
1、Hibernate JPA簡介
1.1、認(rèn)識 hibernate
Hibernate是一個開放源代碼的對象關(guān)系映射框架,它對JDBC進(jìn)行了非常輕量級的對象封裝,它將 POJO與數(shù)據(jù)庫表建立映射關(guān)系,是一個全自動的 orm 框架,hibernate 可以自動生成 SQL 語句,自動執(zhí)行,使得 Java 程序員可以隨心所欲的使用對象編程思維來操縱數(shù)據(jù)庫。
1.2、認(rèn)識 JPA
JPA的全稱:Java Persistence API, 即Java 持久化API,是SUN公司推出的一套基于ORM的規(guī)范,內(nèi)部是由一系列的接口和抽象類構(gòu)成。
JPA通過JDK 5.0注解描述 對象-關(guān)系表 的映射關(guān)系,并將運(yùn)行期的實(shí)體對象持久化到數(shù)據(jù)庫中。
劣勢:
由于對持久層封裝過于完整,導(dǎo)致開發(fā)人員無法對SQL進(jìn)行優(yōu)化,無法靈活使用JDBC的原生SQL,Hibernate封裝了JDBC,所以沒有JDBC直接訪問數(shù)據(jù)庫效率高。要使用數(shù)據(jù)庫的特定優(yōu)化機(jī)制的時候,不適合用Hibernate
框架中使用ORM原則,導(dǎo)致配置過于復(fù)雜,一旦遇到大型項(xiàng)目,比如300張表以上,配置文件和內(nèi)容是非常龐大的,另外,DTO滿天飛,性能和維護(hù)問題隨之而來
如果項(xiàng)目中各個表中關(guān)系復(fù)雜,表之間的關(guān)系很多,在很多地方把lazy都設(shè)置false,會導(dǎo)致數(shù)據(jù)查詢和加載很慢,尤其是級聯(lián)查詢的時候。
優(yōu)勢:
標(biāo)準(zhǔn)化 JPA 是 JCP 組織發(fā)布的 Java EE 標(biāo)準(zhǔn)之一,因此任何聲稱符合 JPA 標(biāo)準(zhǔn)的框架都遵循同樣的架構(gòu),提供相同的訪問API,這保證了基于JPA開發(fā)的企業(yè)應(yīng)用能夠經(jīng)過少量的修改就能夠在不同的JPA框架下運(yùn)行。
容器級特性的支持 JPA框架中支持大數(shù)據(jù)集、事務(wù)、并發(fā)等容器級事務(wù),這使得 JPA 超越了簡單持久化框架的局限,在企業(yè)應(yīng)用發(fā)揮更大的作用。
簡單方便 JPA的主要目標(biāo)之一就是提供更加簡單的編程模型:在JPA框架下創(chuàng)建實(shí)體和創(chuàng)建Java 類一樣簡單,沒有任何的約束和限制,只需要使用 javax.persistence.Entity 進(jìn)行注釋,JPA的框架和接口也都非常簡單,沒有太多特別的規(guī)則和設(shè)計模式的要求,開發(fā)者可以很容易的掌握。JPA基于非侵入式原則設(shè)計,因此可以很容易的和其它框架或者容器集成
查詢能力 JPA的查詢語言是面向?qū)ο蠖敲嫦驍?shù)據(jù)庫的,它以面向?qū)ο蟮淖匀徽Z法構(gòu)造查詢語句,可以看成是Hibernate HQL的等價物。JPA定義了獨(dú)特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一種擴(kuò)展,它是針對實(shí)體的一種查詢語言,操作對象是實(shí)體,而不是關(guān)系數(shù)據(jù)庫的表,而且能夠支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能夠提供的高級查詢特性,甚至還能夠支持子查詢。
高級特性 JPA 中能夠支持面向?qū)ο蟮母呒壧匦?,如類之間的繼承、多態(tài)和類之間的復(fù)雜關(guān)系,這樣的支持能夠讓開發(fā)者最大限度的使用面向?qū)ο蟮哪P驮O(shè)計企業(yè)應(yīng)用,而不需要自行處理這些特性在關(guān)系數(shù)據(jù)庫的持久化。
1.3、JPA 與 hibernate 關(guān)系
JPA規(guī)范本質(zhì)上就是一種ORM規(guī)范,注意不是ORM框架,因?yàn)镴PA并未提供ORM實(shí)現(xiàn),它只是定義了一些規(guī)范,提供了一些編程的API接口,但具體實(shí)現(xiàn)則由服務(wù)廠商來提供實(shí)現(xiàn)
JPA示意圖:

JPA 和 Hibernate 的關(guān)系就像 JDBC 和 JDBC 驅(qū)動的關(guān)系,JPA是規(guī)范,Hibernate除了作為ORM框架之外,它也是一種JPA實(shí)現(xiàn)。
JPA 能取代 Hibernate 嗎?正如同問 JDBC規(guī)范可以驅(qū)動底層數(shù)據(jù)庫嗎?答案是否定的,如果使用JPA規(guī)范進(jìn)行數(shù)據(jù)庫操作,底層需要 hibernate 作為其實(shí)現(xiàn)類完成數(shù)據(jù)持久化工作。
2、搭建開發(fā)環(huán)境(IDEA)
咱們使用Maven方式創(chuàng)建即可
2.1、使用 IDEA 創(chuàng)建 maven 工程(可能會缺少src/test/resources目錄,手動創(chuàng)建和設(shè)置即可)

2.2、導(dǎo)入pom坐標(biāo)

2.3、建立 /resources/META-INF/persistence.xml 配置文件
路徑:配置到類路徑(resources)下的 META-INF 的文件夾下,文件名:persistence.xml
備注:由于主要在 src/test/ 下做測試,所以建議在 src/test/resources/下也建立 META-INF/persistence.xml
IDEA有persistence模板:setting=》file and code Template=》JPA==》Deployment descriptors=》persistenceXX.xml
persistence.xml 內(nèi)容:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
? ?<!-- name:持久化單元名稱,transaction-type:持久化單元事務(wù)類型(JTA:分布式事務(wù)管理,RESOURCE_LOCAL:本地事務(wù)管理) -->
? ?<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
? ? ? ?<!--jpa的實(shí)現(xiàn)方式,配置JPA服務(wù)提供商 -->
? ? ? ?<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
? ? ? ?<!-- 可配可不配,如果配置了順序不能錯,必須在provider之后-->
? ? ? ?<!--<class>com.caochenlei.hibernate.jpa.Customer</class>-->
? ? ? ?<!--可選配置:配置jpa實(shí)現(xiàn)方的配置信息-->
? ? ? ?<properties>
? ? ? ? ? ?<!-- 數(shù)據(jù)庫信息配置:數(shù)據(jù)庫驅(qū)動、數(shù)據(jù)庫地址、數(shù)據(jù)庫賬戶、數(shù)據(jù)庫密碼 -->
? ? ? ? ? ?<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
? ? ? ? ? ?<property name="hibernate.connection.url" value="jdbc:mysql://127.0.0.1:3306/hibernate_jpa"/>
? ? ? ? ? ?<property name="hibernate.connection.username" value="root"/>
? ? ? ? ? ?<property name="hibernate.connection.password" value="password"/>
? ? ? ? ? ?<!-- 配置JPA服務(wù)提供商可選參數(shù) -->
? ? ? ? ? ?<property name="hibernate.show_sql" value="true" /><!-- 自動顯示sql -->
? ? ? ? ? ?<property name="hibernate.format_sql" value="true"/><!-- 格式化sql -->
? ? ? ? ? ?<!-- 自動創(chuàng)建數(shù)據(jù)庫表:
? ? ? ? ? ? ? ?none ? ? ? ?:不會創(chuàng)建表
? ? ? ? ? ? ? ?create ? ? ?: 程序運(yùn)行時創(chuàng)建數(shù)據(jù)庫表(如果有表,先刪除表再創(chuàng)建)
? ? ? ? ? ? ? ?update ? ? ?:程序運(yùn)行時創(chuàng)建表(如果有表,不會創(chuàng)建表)
? ? ? ? ? ? ? ?create-drop : 每次加載hibernate時根據(jù)model類生成表,但是sessionFactory一關(guān)閉,表就自動刪除。
? ? ? ? ? ? ? ?validate ? ?: 每次加載hibernate時,驗(yàn)證創(chuàng)建數(shù)據(jù)庫表結(jié)構(gòu),只會和數(shù)據(jù)庫中的表進(jìn)行比較,不會創(chuàng)建新表,但是會插入新值。
? ? ? ? ? ?-->
? ? ? ? ? ?<property name="hibernate.hbm2ddl.auto" value="update" />
? ? ? ?</properties>
? ?</persistence-unit>
</persistence>
2.4、編寫實(shí)體類和數(shù)據(jù)庫表的映射配置(目的是達(dá)到操作實(shí)體類,就相當(dāng)于操作數(shù)據(jù)庫表)
/**
* 客戶的實(shí)體類
* ? ? ?配置映射關(guān)系
* ? 1.實(shí)體類和表的映射關(guān)系
* ? ? ?@Entity:聲明實(shí)體類
* ? ? ?@Table:配置實(shí)體類和表的映射關(guān)系
* ? ? ? ? ?name : 配置數(shù)據(jù)庫表的名稱
* ? 2.實(shí)體類中屬性和表中字段的映射關(guān)系
*/
@Data
@Entity
@Table(name = "tb_customer")
public class Customer {
? ?/**
? ? * @Id:聲明主鍵的配置
? ? * @GeneratedValue:配置主鍵的生成策略
? ? * ? ? ?strategy:
? ? * ? ? ? ? ?GenerationType.IDENTITY :自增,mysql
? ? * ? ? ? ? ? ? ? ? ?底層數(shù)據(jù)庫必須支持自動增長(底層數(shù)據(jù)庫支持的自動增長方式,對id自增)
? ? * ? ? ? ? ?GenerationType.SEQUENCE : 序列,oracle
? ? * ? ? ? ? ? ? ? ? ?底層數(shù)據(jù)庫必須支持序列
? ? * ? ? ? ? ?GenerationType.TABLE : jpa提供的一種機(jī)制,通過一張數(shù)據(jù)庫表的形式幫助我們完成主鍵自增
? ? * ? ? ? ? ?GenerationType.AUTO : 由程序自動的幫助我們選擇主鍵生成策略
? ? * @Column:配置屬性和字段的映射關(guān)系
? ? * ? ? ?name:數(shù)據(jù)庫表中字段的名稱
? ? */
? ?@Id
? ?@GeneratedValue(strategy = GenerationType.IDENTITY)
? ?@Column(name = "customer_id")
? ?private Long Id; //客戶的主鍵
? ?@Column(name = "customer_name")
? ?private String name;//客戶名稱
? ?@Column(name="customer_age")
? ?private int age;//客戶年齡
? ?@Column(name="customer_sex")
? ?private boolean sex;//客戶性別
? ?@Column(name="customer_phone")
? ?private String phone;//客戶的聯(lián)系方式
? ?@Column(name="customer_address")
? ?private String address;//客戶地址
}
對應(yīng)的數(shù)據(jù)庫表信息:

2.5、測試保存操作的執(zhí)行
? /**
? ? * 測試jpa的保存
? ? * 案例:保存一個客戶到數(shù)據(jù)庫中
? ? * Jpa的操作步驟
? ? * 1.加載配置文件創(chuàng)建工廠(實(shí)體管理器工廠)對象
? ? * 2.通過實(shí)體管理器工廠獲取實(shí)體管理器
? ? * 3.獲取事務(wù)對象,開啟事務(wù)
? ? * 4.完成增刪改查操作
? ? * 5.提交事務(wù)(回滾事務(wù))
? ? * 6.釋放資源
? ? */
? ?@Test
? ?public void testSave() {
? ? ? ?//1.加載配置文件創(chuàng)建工廠(實(shí)體管理器工廠)對象
? ? ? ?EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
? ? ? ?//2.通過實(shí)體管理器工廠獲取實(shí)體管理器
? ? ? ?EntityManager em = factory.createEntityManager();
? ? ? ?//3.獲取事務(wù)對象,開啟事務(wù)
? ? ? ?EntityTransaction tx = em.getTransaction();
? ? ? ?tx.begin();
? ? ? ?//4.完成增刪改查操作:保存一個客戶到數(shù)據(jù)庫中
? ? ? ?Customer customer = new Customer();
? ? ? ?customer.setName("Sam");
? ? ? ?customer.setAddress("Beijing");
? ? ? ?//保存操作
? ? ? ?em.persist(customer);
? ? ? ?//5.提交事務(wù)
? ? ? ?tx.commit();
? ? ? ?//6.釋放資源
? ? ? ?em.close();
? ? ? ?factory.close();
? ?}
2.6、查看日志
Hibernate:
? ?create table tb_customer (
? ? ? customer_id bigint not null auto_increment,
? ? ? ?customer_address varchar(255),
? ? ? ?customer_age integer,
? ? ? ?customer_name varchar(255),
? ? ? ?customer_phone varchar(255),
? ? ? ?customer_sex bit,
? ? ? ?primary key (customer_id)
? ?) engine=InnoDB
Hibernate:
? ?insert
? ?into
? ? ? ?tb_customer
? ? ? ?(customer_address, customer_age, customer_name, customer_phone, customer_sex)
? ?values
? ? ? ?(?, ?, ?, ?, ?)
2.7、這里可以看到為我們自動生成了SQL語句,因?yàn)閤ml 里這里設(shè)置的是 update,所以有表的前提下,不會再生成表
<!-- 自動創(chuàng)建數(shù)據(jù)庫表:
? ?none ? ? ? ?:不會創(chuàng)建表
? ?create ? ? ?: 程序運(yùn)行時創(chuàng)建數(shù)據(jù)庫表(如果有表,先刪除表再創(chuàng)建)
? ?update ? ? ?:程序運(yùn)行時創(chuàng)建表(如果有表,不會創(chuàng)建表)
? ?create-drop : 每次加載hibernate時根據(jù)model類生成表,但是sessionFactory一關(guān)閉,表就自動刪除。
? ?validate ? ?: 每次加載hibernate時,驗(yàn)證創(chuàng)建數(shù)據(jù)庫表結(jié)構(gòu),只會和數(shù)據(jù)庫中的表進(jìn)行比較,不會創(chuàng)建新表,但是會插入新值。
-->
<property name="hibernate.hbm2ddl.auto" value="update" />
搭建完成!
簡單測試:

運(yùn)行結(jié)果,會自動生成HQL語句
