JPA + SpringData 操作資料庫
JPA是Java Persistence API的簡稱,中文名Java持久層API,是JDK 5.0註解或XML描述物件-關係表的對映關係,並將執行期的實體物件持久化到資料庫中。
前言:談起操作資料庫,大致可以分為幾個階段:首先是 JDBC 階段,初學 JDBC 可能會使用原生的 JDBC 的 API,再然後可能會使用資料庫連線池,比如:c3p0、dbcp,還有一些第三方工具,比如 dbutils 等,樓主認為 JDBC 是貫穿始終的,即使到了框架部分,也會對 JDBC 進行整合,此階段還是自己手寫 SQL 語句;下一個階段就是 Hibernate,大家體會到了操作資料庫可以不用自己手動編寫 SQL,呼叫 Hibernate 提供的 API 即可。今天給大家介紹的是操作資料庫的另一個模組 JPA,即 Java 持久層的 API,JPA 如果與 SpringData 結合起來,會發出不一樣的“化學反應”,大家拭目以待~
一、JPA 概述
1. Java Persistence API(Java 持久層 API):用於物件持久化的 API
2. 作用:使得應用程式以統一的方式訪問持久層
3. 前言中提到了 Hibernate,那麼JPA 與 Hibernate究竟是什麼關係呢:
1)JPA 是 Hibernate 的一個抽象,就像 JDBC 和 JDBC 驅動的關係
2)JPA 是一種 ORM 規範,是 Hibernate 功能的一個子集 (既然 JPA 是規範,Hibernate 對 JPA 進行了擴充套件,那麼說 JPA 是 Hibernate 的一個子集不為過)
3)Hibernate 是 JPA 的一個實現
4. JPA 包括三個方面的技術:
1)ORM 對映元資料,支援 XML 和 JDK 註解兩種元資料的形式
2)JPA 的 API
3)查詢語言:JPQL
本文也將詳細介紹JPA ORM 對映元資料的註解方式和 JPA 的 API 以及 JPQL 三個方面
二、JPA 的 Helloworld
1.在 Eclipse 中建立 JPA 的工程:New ---> Project ---> JPA Project 輸入工程名,選擇版本為 2.0,點選 Next,
若是初次建立 JPA 的工程,可能會出錯,提示必須有一個 user library,導致無法建立工廠,此問題的解決方案,LZ另開一個部落格,
2.在當前工程下新建一個 lib 目錄,用來存放各種 jar 包,此時工程的目錄結構為:
匯入 hibernate 的 jar 包和 jpa 的jar包,注意:需要自己手動的 Build Path:
連線資料庫,不要忘記新增 MySQL 的驅動。
3. 大家會發現當我們建立好 jpa 的工程時在 src 的 META-INF 目錄下自動生成了一個 persistence.xml 檔案,我們的配置都編寫在此檔案中,接下來就在此檔案中進行各種配置
1)開啟此檔案,選擇左下角的 Connection 選項,修改 Transaction Type 為 Resource Local,填寫下方的 Driver、Url、User、Password 資訊儲存後,便會在左下角最後一個 Source 選項中自動生成資料庫配置的基本資訊 (lZ 建立的資料庫為 jpa2)
2)其他配置(大家注意一點配置 ORM 產品時,要把 <provider> 節點放到 <provider> 節點上面,否則會出小紅×):
1 <?xml version="1.0" encoding="UTF-8"?> 2 <persistence version="2.0" 3 xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 5 <persistence-unit name="jpa" transaction-type="RESOURCE_LOCAL"> 6 7 <!-- 使用什麼 ORM 產品作為 JPA 的實現 --> 8 <provider>org.hibernate.ejb.HibernatePersistence</provider> 9 10 <properties> 11 <!-- 資料庫連線的基本資訊 --> 12 <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> 13 <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa2" /> 14 <property name="javax.persistence.jdbc.user" value="root" /> 15 <property name="javax.persistence.jdbc.password" value="qiqingqing" /> 16 <!-- 配置 JPA 實現產品的基本屬性,即 Hibernate 的基本屬性 --> 17 <property name="hibernate.show_sql" value="true" /> 18 <property name="hibernate.format_sql" value="true" /> 19 <property name="hibernate.hbm2ddl.auto" value="update" /> 20 </properties> 21 22 </persistence-unit> 23 </persistence>
3)建立持久化類 Customer,併為其新增 JPA 的註解,此時會有錯誤,原因是沒有把 Customer 類新增到 persistence.xml 檔案中,新增進去便沒有了錯誤:
1 package com.software.jpa.helloworld; 2 3 import javax.persistence.Column; 4 import javax.persistence.Entity; 5 import javax.persistence.GeneratedValue; 6 import javax.persistence.GenerationType; 7 import javax.persistence.Id; 8 import javax.persistence.Table; 9 10 @Table(name="JPA_CUSTOMERS") 11 @Entity 12 public class Customer { 13 14 private Integer id; 15 16 private String lastName; 17 18 private String email; 19 20 private Integer age; 21 22 @GeneratedValue(strategy=GenerationType.AUTO) 23 @Id 24 public Integer getId() { 25 return id; 26 } 27 28 public void setId(Integer id) { 29 this.id = id; 30 } 31 32 @Column(name="LAST_NAME") 33 public String getLastName() { 34 return lastName; 35 } 36 37 public void setLastName(String lastName) { 38 this.lastName = lastName; 39 } 40 41 public String getEmail() { 42 return email; 43 } 44 45 public void setEmail(String email) { 46 this.email = email; 47 } 48 49 public Integer getAge() { 50 return age; 51 } 52 53 public void setAge(Integer age) { 54 this.age = age; 55 } 56 57 @Override 58 public String toString() { 59 return "Customer [id=" + id + ", lastName=" + lastName + ", email=" + email + ", age=" + age + "]"; 60 } 61 62 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <persistence version="2.0" 3 xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 5 <persistence-unit name="jpa" transaction-type="RESOURCE_LOCAL"> 6 7 <!-- 使用什麼 ORM 產品作為 JPA 的實現 --> 8 <provider>org.hibernate.ejb.HibernatePersistence</provider> 9 10 <!-- 新增持久化類 --> 11 <class>com.software.jpa.helloworld.Customer</class> 12 13 <properties> 14 <!-- 資料庫連線的基本資訊 --> 15 <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> 16 <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa2" /> 17 <property name="javax.persistence.jdbc.user" value="root" /> 18 <property name="javax.persistence.jdbc.password" value="qiqingqing" /> 19 <!-- 配置 JPA 實現產品的基本屬性,即 Hibernate 的基本屬性 --> 20 <property name="hibernate.show_sql" value="true" /> 21 <property name="hibernate.format_sql" value="true" /> 22 <property name="hibernate.hbm2ddl.auto" value="update" /> 23 </properties> 24 25 </persistence-unit> 26 </persistence>
4)建立一個測試類進行測試,生成資料表,插入了資料,至此 JPA 的 Helloworld 完成。
1 package com.software.jpa.helloworld; 2 3 import javax.persistence.EntityManager; 4 import javax.persistence.EntityManagerFactory; 5 import javax.persistence.EntityTransaction; 6 import javax.persistence.Persistence; 7 8 public class Main { 9 10 public static void main(String[] args) { 11 12 //1.建立 EntityManagerFactory 13 String persistenceUnitName = "jpa"; 14 EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName); 15 16 //2.建立 EntityManager 17 EntityManager entityManager = entityManagerFactory.createEntityManager(); 18 19 //4.開啟事務 20 EntityTransaction transaction = entityManager.getTransaction(); 21 transaction.begin(); 22 23 //5.進行持久化操作 24 Customer customer = new Customer(); 25 customer.setLastName("AA"); 26 customer.setEmail("[email protected]"); 27 customer.setAge(20); 28 29 entityManager.persist(customer); 30 31 //6.提交事務 32 transaction.commit(); 33 34 //7.關閉 EntityManager 35 entityManager.close(); 36 37 //8.關閉 EntityManagerFactory 38 entityManagerFactory.close(); 39 40 } 41 42 }
三、JPA 的基本註解
看了 JPA 的 Helloworld 之後說一下 JPA 的基本註解
1. @Entity :修飾實體類,指明該類將對映到指定的資料表,例如:Customer 類預設的資料表名為 customer
2. @Table :當實體類與對映的資料庫表名不同名時需要使用 @Table 註解,該註解與 @Entity 註解並列使用,使用其 name 屬性指明資料庫的表名
1 @Table(name = "JPA_CUSTOMER") 2 @Entity 3 public class Customer {
3. @Id :標識該屬性為主鍵,一般標註在該屬性的 getter 方法上
4. @GeneratedValue :標註主鍵的生成策略,通過其 strategy 屬性。通常與 @Id 註解一起使用。預設情況下 JPA 會自動選擇一個最適合底層資料庫的主鍵生成策略,MySQL 預設為 AUTO,常用策略有:
–IDENTITY:採用資料庫 ID自增長的方式來自增主鍵欄位,Oracle 不支援這種方式;
–AUTO: JPA自動選擇合適的策略,是預設選項;
–SEQUENCE:通過序列產生主鍵,通過 @SequenceGenerator 註解指定序列名,MySql 不支援這種方式
–TABLE:通過表產生主鍵,框架藉由表模擬序列產生主鍵,使用該策略可以使應用更易於資料庫移植
5. @Basic :用於沒有任何標註的 getXxx() 方法,預設即為 @Basic,所以若一個 getter 方法無任何註解,可以使用 @Basic 註解,也可以不使用
6. @Column :當實體的屬性與其對映的資料表的列不同名時使用,一般用於 getter 方法上。其 name 屬性用來指明此屬性在資料表中對應的列名;unique 屬性指明是否為唯一約束;nullable 屬性用來指明是否可以為空,false 為不能為空;length 屬性指明此列的長度。
7. @Transient :標註此註解後在建立資料表的時候將會忽略該屬性 Customer 類並沒有 info 這個屬性,所以資料庫中也不應該有 info 這個欄位
8. @Temporal :向資料庫對映日期(Date)屬性時用來調整對映的精度。Date 型別的資料有 DATE, TIME, 和 TIMESTAMP 三種精度(即單純的日期,時間,或者兩者兼備).
Birth 屬性應該使用 DATE 型別(生日只具體到日即可,如:2015-10-22),而 CreateTime 應該使用 TIMESTAMP 型別(建立時間應該具體到秒,如:2017-10-11 22:39:13)
補衝:使用 TABLE 生成主鍵詳解
1.建立一個數據表 jpa_id_generators,並新增幾條資料
2. 配置使用 TABLE 主鍵生成策略
1 //使用 TABLE 主鍵生成策略 2 @TableGenerator(name="ID_GENERATOR", //該主鍵生成策略的名稱,與 @GeneratedValue 的 generator 屬性值對應 3 table="jpa_id_generators", // 指明根據哪個表生成主鍵 4 pkColumnName="PK_NAME", // 使用 pkColumnName pkColumnValue valueColumnName 三個屬性唯一的定位一個點 5 pkColumnValue="CUSTOMER_ID", 6 valueColumnName="PK_VALUE", 7 allocationSize=100) //指定每次增加的數量 8 @GeneratedValue(strategy=GenerationType.TABLE, generator="ID_GENERATOR") 9 @Id 10 public Integer getId() { 11 return id; 12 }
附一張表說明: