【java框架】JPA(1) -- JPA入門


1.   JPA認識

JPA是Java Persistence API的簡稱,它是Sun公司在充分吸收現有ORM框架(Hibernate)的基礎上,開發而來的一個Java EE 5.0平台標准的開源的對象關系映射(ORM)規范。

Hibernate與JPA的關系:

Hibernate是一個開放源代碼的對象關系映射(ORM)框架,它對JDBC進行了非常輕量級的對象封裝,將POJO與數據庫表建立映射關系,是一個全自動的ORM框架,Hibernate可以自動生成SQL語句,自動執行,使Java程序員可以隨心所欲地使用面向對象思維來操縱數據庫。

而JPA是Sun官方提出的Java持久化規范,而JPA是在充分吸收Hibernate、TopLink等ORM框架的基礎上發展而來的。

總結一句話就是:JPA是持久化的關系映射規范、接口API,而Hibernate是其實現。

1.1.  JPA的優缺點

優點:

①    操作代碼很簡單,插入—persist、修改—merge、查詢—find、刪除—remove;

②    直接面向持久化對象操作;

③    提供了世界級的數據緩存:包括一級緩存、二級緩存、查詢緩存;

④    切換數據庫移植性強,對應各種數據庫抽取了一個方言配置接口,換數據庫只需修改方言配置、驅動jar包、數據庫連接4個信息即可。

缺點:

①    不能干預SQL語句的生成;

②    對於SQL優化效率要求較高的項目,不適合使用JPA;

③    對於數據量上億級別的大型項目,也不適合使用JPA。

2.   手動創建一個Hello World的JPA項目

2.1.  導入JPA項目所需jar包

Hibernate版本可以到官網進行下載:http://hibernate.org/orm/releases/

這里作為學習使用Hibernate 4.3.8的版本jar包,即JPA2.1版本為例進行項目jar包的構建:

導入項目所需要的Hibernate的jar包分為三類:

①    Hibernate所必需的jar包:

目錄路徑位置:\hibernate-release-4.3.8.Final\lib\required

導入如下圖所示jar包集合:

②    還需要導入JPA支持的jar包,目錄路徑:\hibernate-release-4.3.8.Final\lib\jpa與數據庫Mysql連接驅動jar包;

2.2.  配置核心配置文件persistence.xml

配置文件必需放在項目的classpath目錄的資源文件resources\META-INF目錄下(JPA規范要求);

persistence.xml文件具體配置如下:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
    <!--持久化單元 name:和項目名稱對應-->
    <persistence-unit name="cn.yif.jpa01" transaction-type="RESOURCE_LOCAL">
        <properties>
            <!-- 必須配置4個連接數據庫屬性:配置信息可以在project/etc/hibernate.properties中找到 -->
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
            <property name="hibernate.connection.url" value="jdbc:mysql:///jpa01_0307" />
            <property name="hibernate.connection.username" value="root" />
            <property name="hibernate.connection.password" value="admin" />

            <!-- 必須配置1個數據庫方言屬性 -->
            <!-- 實現跨數據庫關鍵類 :查詢MySQLDialect的getLimitString方法 -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />

            <!-- 可選配置 -->
            <!-- 是否自動生成表 -->
            <property name="hibernate.hbm2ddl.auto" value="create" />
            <!-- 是否顯示sql -->
            <property name="hibernate.show_sql" value="true" />
            <!-- 格式化sql -->
            <property name="hibernate.format_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

 

2.3.創建持久化Domain類Employee

package cn.yif.domain;

import javax.persistence.*;

//@Entity表示該類是由jpa管理的持久化對象,對應數據庫中的一張表
@Entity
//@Table表示對應數據庫的表名
@Table(name = "t_employee")
public class Employee {
    //@Id是必須的注解,表示對應數據庫的主鍵
    @Id
    //@GeneratedValue表示主鍵的生成策略,多數都是使用AUTO
    //@GeneratedValue默認不配置也是AUTO
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    //@Column表示如果數據庫列名與屬性名不一致,需要配置
    @Column(name = "e_name") 
    private String name;
    @Column(name = "e_age")
    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

2.4.創建Junit4測試類代碼

import cn.yif.domain.Employee;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JPAHelloTest {

   @Test
   public void testInsertEmpByJPA(){
        Employee employee = new Employee();
        employee.setName("高偉翔");
        employee.setAge(34);
        // 對應配置文件里面的persistence-unit name="cn.yif.jpa01"
        // 通過持久化類創建一個實體類管理工廠
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("cn.yif.jpa01");
        //創建一個實體管理類,可以實現CRUD
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        //由entityManager來開啟事務
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        //持久操作CRUD 寫入persist
        entityManager.persist(employee);
        // 提交事務
        transaction.commit();
        //關閉資源
        entityManager.close();
        entityManagerFactory.close();
    }
}

通過以上的步驟,就可以在創建的jpa01_0307數據庫里面由JPA自動創建一張t_employee表並插入一條數據:

 

 

3.   實現完整的JPA CRUD流程

3.1.抽取JPAUtil類

package cn.yif.utils;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 * 工具類:單例模式/靜態單例模式  靜態方法
 */
public class JPAUtil {
    // 私有化這個構造器,不讓其它人創建這個類
    private JPAUtil(){}

    // 實體管理工廠
    // 注意:EntityManagerFactory這個類是線程安全
    private static EntityManagerFactory entityManagerFactory;

    /**
     * 靜態代碼塊,類加載的時候就會執行里面的代碼,只會執行一次
     */
    static{
        try {
            entityManagerFactory = Persistence.createEntityManagerFactory("cn.yif.jpa01");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("拿到EntityManagerFactory運行時出錯:"+e.getMessage());
        }
    }

    // 拿到一個EntityManager對象
    // 每次拿EntityManager都需要重新創建(EntityManager不是線程安全的對象,每次使用都重新創建一次)
    public static EntityManager getEntityManager(){
        return entityManagerFactory.createEntityManager();
    }

    public static void close(EntityManager entityManager){
        //關閉資源
        entityManager.close();
        entityManagerFactory.close();
    }
}

 

4.   persitence.xml中hibernate.hbm2ddl.auto屬性值配置

如上,hibernate.hbm2ddl.auto屬性的value值一共有4種配置:create-drop、create、update、validate。下面來解釋這四種不同配置場景的區別與作用:

①    create-drop

create-drop作用:先刪除表,在創建表,最后再刪除表;

注意:必須執行entityManagerFactory.close()代碼才會最后刪除表,執行drop表功能

 

 

②    create

 

create作用:先刪除表,在創建表。

③    update

update作用:

如果數據庫中沒有當前JPA持久化的表就根據最新映射來創建表;

如果數據庫已經有表了,則不會刪除原來表的任何結構,只會新增列;

注意如果是表里面沒有這個屬性,映射信息domain類中有,則會增加這個屬性

④   validate

validate作用:

如果數據庫中表不存在或者domain類中的屬性大於數據庫表中的字段,會拋出異常;

會驗證映射信息domain類與數據庫表中的對應字段,如果一一對應或者映射小於數據庫表中的字段,不會拋出異常

5.   單表映射配置細節

5.1.持久類domain映射配置細節

5.1.1.     日期與時間類型格式

①    日期與時間格式配置

使用@Temporal注解配置:

@Temporal(TemporalType.TIMESTAMP)

默認配置,會設置數據庫表的時間格式為:“yyyy-MM-dd hh:mm:ss"

@Temporal(TemporalType.DATE)

會設置數據庫表的時間格式為:”yyyy-MM-dd"

 

@Temporal(TemporalType.TIME)

會設置數據庫表的時間格式為:“hh:mm:ss”

持久類domain配置

@Temporal(TemporalType.TIMESTAMP)
private Date createTime; // 創建時間:格式--"yyyy-MM-dd hh:mm:ss"(年--月--日--時--分--秒)

@Temporal(TemporalType.DATE)
private Date brithday; // 生日:格式--"yyyy-MM-dd"(年--月--日)

@Temporal(TemporalType.TIME)
private Date classTime; // 上課時間:格式--"hh:mm:ss""(時--分--秒)

具體設置格式如下:

 

5.1.2.     文本長度與長文本類型

domain類對應普通表中的長度如果不配置長度,默認vachar字段類型在數據庫表中的長度會給到255,比較占用空間,我們可以通過JPA注解配置來指定固定的length長度值。

 

普通String類屬性字段長度配置:

@Column(name = "t_name", length = 20)

@Column(name = "pwd", length = 100)

在@Column注解上加上length長度配置,即可指定數據庫表中varchar字段的長度;

 

長文本類型屬性字段配置:

在對應domain類的屬性上加上注解@Lob,對應這個字段在數據庫中就會被設置成longtext類型,能儲存大文本。

持久類domain配置

@Lob  // 設置為長文本類型
private String Intro; // 個人簡介:長文本類型

 

5.1.3.     屬性約束設置

非空約束:

配置@Column(nullable = false)

 

唯一約束:

配置@Column(unique = true)

 

 

 

5.1.4.     其他映射配置

①    臨時屬性配置:Transient(臨時屬性—該屬性在持久化對象上有,但是不會寫入數據庫);

@Transient
private String temp;

②   設置是否能更新able:@Column(updatable=false),表示添加的時候會進行添加,但是修改的時候不能修改(了解就行,一般不用);

③    設置是否能添加able:@Column(insertable=false),表示添加的時候不能操作,但是修改的時候可以操作修改(了解就行,一般不用);

④    自定義持久類domain屬性規則:@Column(columnDefinition=”int check(age > 18)”),Mysql不支持這個規則,Oracle才支持(了解就行,Mysql數據庫用不了)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM