1、ORM概述
-
ORM(Object-Relational Mapping) 表示對象關係映射。在面向對象的軟件開發中,通過ORM,就可以把對象映射到關係型數據庫中。只要有一套程序能夠做到建立對象與數據庫的關聯,操作對象就可以直接操作數據庫數據,就可以說這套程序實現了ORM對象關係映射
-
簡單的說:ORM就是建立實體類和數據庫表之間的關係,從而達到操作實體類就相當於操作數據庫表的目的。
常見的orm框架:Mybatis(ibatis)、Hibernate
2、爲什麼使用ORM
ORM則會大大減少重複性代碼。下圖是使用JDBC操作數據庫連接查詢的語句,可見語句十分繁瑣。
3、什麼是JPA
-
JPA的全稱是Java Persistence API, 即Java 持久化API,是SUN公司推出的一套基於ORM的規範,內部是由一系列的接口和抽象類構成。
-
JPA通過JDK 5.0註解描述對象-關係表的映射關係,並將運行期的實體對象持久化到數據庫中。
4、JPA與Hibernate的關係
- JPA和Hibernate的關係就像JDBC和JDBC驅動的關係,JPA是規範,Hibernate除了作爲ORM框架之外,它也是一種JPA實現。JPA怎麼取代Hibernate呢?JDBC規範可以驅動底層數據庫嗎?答案是否定的,也就是說,如果使用JPA規範進行數據庫操作,底層需要hibernate作爲其實現類完成數據持久化工作。
- 這裏不詳細展開hibernate這種框架,hibernate實現數據庫操作是對JDBC進行了非常輕量級的對象封裝
- 下圖展現了各個上述的關係。
5、JPA的基本操作
-
jpa操作的操作步驟
1. 加載配置文件創建實體管理器工廠
Persisitence:靜態方法(根據持久化單元名稱創建實體管理器工廠)
createEntityMnagerFactory(持久化單元名稱)
作用:創建實體管理器工廠2. 根據實體管理器工廠,創建實體管理器
EntityManagerFactory :獲取EntityManager對象
方法:createEntityManager
* 內部維護的很多的內容
內部維護了數據庫信息,
維護了緩存信息
維護了所有的實體管理器對象
再創建EntityManagerFactory的過程中會根據配置創建數據庫表
* EntityManagerFactory的創建過程比較浪費資源
特點:線程安全的對象
多個線程訪問同一個EntityManagerFactory不會有線程安全問題
* 如何解決EntityManagerFactory的創建過程浪費資源(耗時)的問題?
思路:創建一個公共的EntityManagerFactory的對象
* 靜態代碼塊的形式創建EntityManagerFactory3. 創建事務對象,開啓事務
EntityManager對象:實體類管理器
beginTransaction : 創建事務對象
presist : 保存
merge : 更新
remove : 刪除
find/getRefrence : 根據id查詢
Transaction 對象 : 事務
begin:開啓事務
commit:提交事務
rollback:回滾
4. 增刪改查操作
5. 提交事務
6. 釋放資源
6、抽取JPAUtil工具類
- 由於jpa的前三操作都是固定的,所以可以抽取出JPAUtil工具類,事務操作通過getEntityManager()方法就可以獲得EntityManager對象,從而進行操作。
- JPAUtil工具類
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public final class JPAUtil {
// JPA的實體管理器工廠:相當於Hibernate的SessionFactory
private static EntityManagerFactory em;
// 使用靜態代碼塊賦值
static {
// 注意:該方法參數必須和persistence.xml中persistence-unit標籤name屬性取值一致
em = Persistence.createEntityManagerFactory("myPersistUnit");
}
/**
* 使用管理器工廠生產一個管理器對象
*
* @return
*/
public static EntityManager getEntityManager() {
return em.createEntityManager();
}
}
7、根據JPAUtil工具類對數據庫進行操作
- 配置數據庫連接(src\main\resources\META-INF),可以是xml、yml、properties,本例使用xml。
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--需要配置persistence-unit節點
持久化單元:
name:持久化單元名稱
transaction-type:事務管理的方式
JTA:分佈式事務管理
RESOURCE_LOCAL:本地事務管理
-->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--jpa的實現方式 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--可選配置:配置jpa實現方的配置信息-->
<properties>
<!-- 數據庫信息
用戶名,javax.persistence.jdbc.user
密碼, javax.persistence.jdbc.password
驅動, javax.persistence.jdbc.driver
數據庫地址 javax.persistence.jdbc.url
-->
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="111111"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
<!--配置jpa實現方(hibernate)的配置信息
顯示sql : false|true
自動創建數據庫表 : hibernate.hbm2ddl.auto
create : 程序運行時創建數據庫表(如果有表,先刪除表再創建)
update :程序運行時創建表(如果有表,不會創建表)
none :不會創建表
-->
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
-
創建客戶實體類,Jpa中在實體類中使用的註解:
1. @Entity:聲明實體類 2. @Table : 配置實體類和表的映射關係 3. @Id:聲明主鍵的配置 4. @GeneratedValue:配置主鍵的生成策略 5. @Column:配置屬性和字段的映射關係:@Colum屬性要麼全寫,要麼都不寫。
package cn.itcast.domain;
import javax.persistence.*;
/**
* 客戶的實體類
* 配置映射關係
*
*
* 1.實體類和表的映射關係
* @Entity:聲明實體類
* @Table : 配置實體類和表的映射關係
* name : 配置數據庫表的名稱
* 2.實體類中屬性和表中字段的映射關係
*
*
*/
@Entity
@Table(name = "cst_customer")
public class Customer {
/**
* @Id:聲明主鍵的配置
* @GeneratedValue:配置主鍵的生成策略
* strategy
* GenerationType.IDENTITY :自增,mysql
* * 底層數據庫必須支持自動增長(底層數據庫支持的自動增長方式,對id自增)
* GenerationType.SEQUENCE : 序列,oracle
* * 底層數據庫必須支持序列
* GenerationType.TABLE : jpa提供的一種機制,通過一張數據庫表的形式幫助我們完成主鍵自增
* GenerationType.AUTO : 由程序自動的幫助我們選擇主鍵生成策略
* @Column:配置屬性和字段的映射關係
* name:數據庫表中字段的名稱
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long custId; //客戶的主鍵
@Column(name = "cust_name")
private String custName;//客戶名稱
@Column(name="cust_source")
private String custSource;//客戶來源
@Column(name="cust_level")
private String custLevel;//客戶級別
@Column(name="cust_industry")
private String custIndustry;//客戶所屬行業
@Column(name="cust_phone")
private String custPhone;//客戶的聯繫方式
@Column(name="cust_address")
private String custAddress;//客戶地址
public Long getCustId() {
return custId;
}
public void setCustId(Long custId) {
this.custId = custId;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
@Override
public String toString() {
return "Customer{" +
"custId=" + custId +
", custName='" + custName + '\'' +
", custSource='" + custSource + '\'' +
", custLevel='" + custLevel + '\'' +
", custIndustry='" + custIndustry + '\'' +
", custPhone='" + custPhone + '\'' +
", custAddress='" + custAddress + '\'' +
'}';
}
}
- 調用JPAUtil工具類進行保存操作。
/**
* 保存一個實體
*/
@Test
public void testAdd() {
// 定義對象
Customer c = new Customer();
c.setCustName("盧本偉");
c.setCustLevel("賭怪");
c.setCustSource("網絡");
c.setCustIndustry("傘兵");
c.setCustAddress("盧本偉廣場");
c.setCustPhone("11111111");
EntityManager em = null;
EntityTransaction tx = null;
try {
// 獲取實體管理對象
em = JPAUtil.getEntityManager();
// 獲取事務對象
tx = em.getTransaction();
// 開啓事務
tx.begin();
// 執行操作
em.persist(c);
// 提交事務
tx.commit();
} catch (Exception e) {
// 回滾事務
tx.rollback();
e.printStackTrace();
} finally {
// 釋放資源
em.close();
}
}
- 查詢操作,有兩種。
Customer c1 = em.find(Customer.class, 1L);//立即加載查詢策略
Customer c1 = em.getReference(Customer.class, 1L)//延遲加載查詢策略
- 刪除操作
Customer c1 = em.find(Customer.class, 6L);
em.remove(c1);
- 修改操作
Customer c1 = em.find(Customer.class, 6L);
c1.setCustName("盧本偉廣場");