對(duì)象持久化API之JPA入門教程

JPA:Java Persistence API,用于對(duì)象持久化的 API

注意:JPA是規(guī)范,不是ORM框架,是ORM框架的規(guī)范,JPA沒(méi)有實(shí)現(xiàn)ORM,具體實(shí)現(xiàn)由ORM廠商提供

現(xiàn)在JPA具體實(shí)現(xiàn)框架有:Hibernate、OpenJPA、TopLink

JPA的優(yōu)勢(shì):##

標(biāo)準(zhǔn)化: 提供相同的 API,這保證了基于JPA 開(kāi)發(fā)的企業(yè)應(yīng)用能夠經(jīng)過(guò)少量的修改就能夠在不同的 JPA 框架下運(yùn)行。
簡(jiǎn)單易用,集成方便: JPA 的主要目標(biāo)之一就是提供更加簡(jiǎn)單的編程模型,在 JPA 框架下創(chuàng)建實(shí)體和創(chuàng)建 Java 類一樣簡(jiǎn)單,只需要使用 javax.persistence.Entity 進(jìn)行注釋;JPA 的框架和接口也都非常簡(jiǎn)單,
可媲美JDBC的查詢能力: JPA的查詢語(yǔ)言是面向?qū)ο蟮模琂PA定義了獨(dú)特的JPQL,而且能夠支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能夠提供的高級(jí)查詢特性,甚至還能夠支持子查詢。
支持面向?qū)ο蟮母呒?jí)特性: JPA 中能夠支持面向?qū)ο蟮母呒?jí)特性,如類之間的繼承、多態(tài)和類之間的復(fù)雜關(guān)系,最大限度的使用面向?qū)ο蟮哪P?/p>

JPA主要包括這三方面的技術(shù):##

ORM 映射元數(shù)據(jù):JPA 支持 XML 和 JDK 5.0 注解兩種元數(shù)據(jù)的形式,元數(shù)據(jù)描述對(duì)象和表之間的映射關(guān)系,框架據(jù)此將實(shí)體對(duì)象持久化到數(shù)據(jù)庫(kù)表中。
JPA 的 API:用來(lái)操作實(shí)體對(duì)象,執(zhí)行CRUD操作,框架在后臺(tái)完成所有的事情,開(kāi)發(fā)者從繁瑣的 JDBC和 SQL代碼中解脫出來(lái)。
查詢語(yǔ)言(JPQL):這是持久化操作中很重要的一個(gè)方面,通過(guò)面向?qū)ο蠖敲嫦驍?shù)據(jù)庫(kù)的查詢語(yǔ)言查詢數(shù)據(jù),避免程序和具體的 SQL 緊密耦合。

使用JPA實(shí)現(xiàn)持久化對(duì)象的步驟

(1)創(chuàng)建 persistence.xml, 在這個(gè)文件中配置持久化單元
需要指定跟哪個(gè)數(shù)據(jù)庫(kù)進(jìn)行交互;
需要指定 JPA 使用哪個(gè)持久化的框架以及配置該框架的基本屬性
(2)創(chuàng)建實(shí)體類, 使用 annotation 來(lái)描述實(shí)體類跟數(shù)據(jù)庫(kù)表之間的映射關(guān)系.
(3)使用 JPA API 完成數(shù)據(jù)增加、刪除、修改和查詢操作
創(chuàng)建 EntityManagerFactory (對(duì)應(yīng) Hibernate 中的 SessionFactory);
創(chuàng)建 EntityManager (對(duì)應(yīng) Hibernate 中的Session);

使用Eclipse創(chuàng)建一個(gè)jpa項(xiàng)目

這里寫(xiě)圖片描述

加入需要的jar
hibernate-release-4.3.6.Final\lib\required*.jar
hibernate-release-4.3.6.Final\lib\jpa*.jar

這里寫(xiě)圖片描述

echache需要的jar


這里寫(xiě)圖片描述

當(dāng)然還有數(shù)據(jù)庫(kù)連接的jar

配置好放在META-INF下面的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="jpaDemo" transaction-type="RESOURCE_LOCAL">
    <!-- 配置Hibernate JPA作為JPA的實(shí)現(xiàn)ORM框架,若項(xiàng)目只有一個(gè)JPA實(shí)現(xiàn)產(chǎn)品,那么這個(gè)配置可以不寫(xiě) -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
    
    <!-- 添加持久化類 -->
        <class>com.jpaDemo.entity.Customer</class>
        <class>com.jpaDemo.entity.Order</class>
    
    <!-- 
        配置二級(jí)緩存的策略 
        ALL:所有的實(shí)體類都被緩存
        NONE:所有的實(shí)體類都不被緩存. 
        ENABLE_SELECTIVE:標(biāo)識(shí) @Cacheable(true) 注解的實(shí)體類將被緩存
        DISABLE_SELECTIVE:緩存除標(biāo)識(shí) @Cacheable(false) 以外的所有實(shí)體類
        UNSPECIFIED:默認(rèn)值,JPA 產(chǎn)品默認(rèn)值將被使用
        -->
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
        
        <properties>
            <!-- 連接數(shù)據(jù)庫(kù)的基本信息 -->
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="root"/>
            <!-- 配置 JPA 實(shí)現(xiàn)產(chǎn)品的基本屬性. 配置 hibernate 的基本屬性 -->
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <!-- 二級(jí)緩存相關(guān) -->
            <property name="hibernate.cache.use_second_level_cache" value="true"/>
            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
            <property name="hibernate.cache.use_query_cache" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

echache.xml:

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <diskStore path="java.io.tmpdir"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

    <!--Predefined caches.  Add your cache configuration settings here.
        If you do not have a configuration for your cache a WARNING will be issued when the
        CacheManager starts

        The following attributes are required for defaultCache:

        name              - Sets the name of the cache. This is used to identify the cache. It must be unique.
        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->

    <!-- Sample cache named sampleCache1
        This cache contains a maximum in memory of 10000 elements, and will expire
        an element if it is idle for more than 5 minutes and lives for more than
        10 minutes.

        If there are more than 10000 elements it will overflow to the
        disk cache, which in this configuration will go to wherever java.io.tmp is
        defined on your system. On a standard Linux system this will be /tmp"
        -->
    <cache name="sampleCache1"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <!-- Sample cache named sampleCache2
        This cache contains 1000 elements. Elements will always be held in memory.
        They are not expired. -->
    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /> -->

    <!-- Place configuration for your caches following -->

</ehcache>

實(shí)體類:

package com.jpaDemo.entity;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

@Cacheable(true)
@Table(name="JPA_CUTOMERS")
@Entity
public class Customer {

    private Integer id;
    private String lastName;

    private String email;
    private int age;
    
    private Date createdTime;
    private Date birth;
    
    public Customer() {
        // TODO Auto-generated constructor stub
    }
    
    public Customer(String lastName, int age) {
        super();
        this.lastName = lastName;
        this.age = age;
    }



    private Set<Order> orders = new HashSet<>();

//  @TableGenerator(name="ID_GENERATOR",
//          table="jpa_id_generators",
//          pkColumnName="PK_NAME",
//          pkColumnValue="CUSTOMER_ID",
//          valueColumnName="PK_VALUE",
//          allocationSize=100)
//  @GeneratedValue(strategy=GenerationType.TABLE,generator="ID_GENERATOR")
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Id
    public Integer getId() {
        return id;
    }

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

    @Column(name="LAST_NAME",length=50,nullable=false)
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    
    @Temporal(TemporalType.TIMESTAMP)
    public Date getCreatedTime() {
        return createdTime;
    }

    public void setCreatedTime(Date createdTime) {
        this.createdTime = createdTime;
    }

    @Temporal(TemporalType.DATE)
    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }
    
    //映射單向 1-n 的關(guān)聯(lián)關(guān)系
    //使用 @OneToMany 來(lái)映射 1-n 的關(guān)聯(lián)關(guān)系
    //使用 @JoinColumn 來(lái)映射外鍵列的名稱
    //可以使用 @OneToMany 的 fetch 屬性來(lái)修改默認(rèn)的加載策略
    //可以通過(guò) @OneToMany 的 cascade 屬性來(lái)修改默認(rèn)的刪除策略. 
    //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 屬性, 則 @OneToMany 端就不能再使用 @JoinColumn 屬性了. 
//  @JoinColumn(name="CUSTOMER_ID")
    @OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.REMOVE},mappedBy="customer")
    public Set<Order> getOrders() {
        return orders;
    }

    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }

    //工具方法. 不需要映射為數(shù)據(jù)表的一列. 
    @Transient
    public String getInfo(){
        return "lastName: " + lastName + ", email: " + email;
    }

    @Override
    public String toString() {
        return "Customer [id=" + id + ", lastName=" + lastName + ", email="
                + email + ", age=" + age + ", createdTime=" + createdTime
                + ", birth=" + birth + "]";
    }

}

測(cè)試類:

package com.jpaDemo.test;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

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

import com.jpaDemo.entity.Customer;

public class MyTest {
public static void main(String[] args) {
        
        //1. 創(chuàng)建 EntitymanagerFactory
        String persistenceUnitName = "jpaDemo";
        
        Map<String, Object> properites = new HashMap<String, Object>();
        properites.put("hibernate.show_sql", true);
        
        EntityManagerFactory entityManagerFactory = 
                Persistence.createEntityManagerFactory(persistenceUnitName, properites);
                
        //2. 創(chuàng)建 EntityManager. 類似于 Hibernate 的 SessionFactory
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        
        //3. 開(kāi)啟事務(wù)
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        
        //4. 進(jìn)行持久化操作
        Customer customer = new Customer();
        customer.setAge(12);
        customer.setEmail("123@qq.com");
        customer.setLastName("Tom");
        customer.setBirth(new Date());
        customer.setCreatedTime(new Date());
        
        entityManager.persist(customer);
        
        //5. 提交事務(wù)
        transaction.commit();
        
        //6. 關(guān)閉 EntityManager
        entityManager.close();
        
        //7. 關(guān)閉 EntityManagerFactory
        entityManagerFactory.close();
    }
}

這里寫(xiě)圖片描述
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容