Jpa使用教程(1)

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的對象
    * 靜態代碼塊的形式創建EntityManagerFactory

    3. 創建事務對象,開啓事務
    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("盧本偉廣場");
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章