JPA 簡單實體映射和EntityManagerAPI


【常用注解】

使用JPA 指定映射關系時,有兩種方式,一種是使用xml 方式,另一種是注解方式,筆者推薦使用注解方式。在JPA 映射簡單實體時,常用的注解如下:

@Entity:修飾實體類對象,表示該實體類對象進行數據庫映射

@Table(name="***"):指定實體類對象映射的表名稱

@Id: 指定主鍵

@GeneratedValue(strategy=GenerationType.AUTO):指定主鍵生成方式,默認為Auto。

    IDENTITY:采用數據庫 ID自增長的方式來自增主鍵字段,Oracle 不支持這種方式;
    AUTO: JPA自動選擇合適的策略,是默認選項;
    SEQUENCE:通過序列產生主鍵,通過 @SequenceGenerator 注解指定序列名,MySql 不支持這種方式
    TABLE:通過表產生主鍵,框架借由表模擬序列產生主鍵,使用該策略可以使應用更易於數據庫移植。

@Column(name="s_name",length=20,unique=true,nullable=false, insertable=true, updatable=true):修飾屬性, 指定列名稱和相關限制

@Enumerated(EnumType.STRING):修飾枚舉類屬性,

                      EnumType.STRING: 指定數據庫中存儲的是字符串類型,

                       EnumTypee.ORDINAL:指定數據庫 存儲的類型為枚舉的索引(0,1,2,3...)

@Temporal(TemporalType.TIME):修飾日期類型:

                       TemporalType.DATE: 指定映射數據庫中的DATE 類型,只存儲日期

                       TemporalType.TIME: 指定映射數據庫 中的TIME類型, 只存儲時間

                       TemporalType.TIMESTAMP:指定映射數據庫中的TIMESTAMP類型

@Transient:指定不映射的屬性

@Lob:修飾 byte[] 數組,二進制文件

@Basic(fetch=FetchType.LAZY) : 默認注解,如果字段不添加任何注解,則默認添加了此注解。可以通過fetch 屬性指定大數據字段延時加載,目前在Hibernate中並未能實現,或許是Hibernate的一個bug。

@NamedQueries({
@NamedQuery(name="***",query="*** hql ***"),
@NamedQuery(name="***",query="*** hql ***")
}): 命名查詢注解,指定命名查詢語句,query字段只能寫JPQL 查詢語句,不能寫普通的sql 語句。



【JPA 常用API】

 





【簡單實體對象:PersonEntity.java】

package org.zgf.jpa.entity;
 
import java.util.Date;
 
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
 
import org.zgf.jpa.enumer.Gender;
 
 
 
@Table(name="tb_person")
@Entity
@NamedQueries({ //命名查詢注解:只能寫JPQL 語句
    @NamedQuery(name="queryAllByJpql",query="from PersonEntity personEntity"),
    @NamedQuery(name="queryByName",query="from PersonEntity personEntity where personEntity.name = :name")
})
public class PersonEntity {
    
    /**
     * 測試主鍵生成策略
     * GenerationType.AUTO: 根據數據庫的默認規則來生成主鍵
     * GenerationType.IDENTITY:數據庫自增(mysql 適用,Oracle不適用)                                                                                                        
     * GenerationType.SEQUENCE:序列生成方式,(Oracle適用,mysql 不適用)
     */
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;
    
    /***
     * 數據庫字段限制:
     * Column可以指定數據庫 字段的名稱 ,長度,唯一性,是否可以為空,是否可以插入,是否可以更新
     */
    @Column(name="s_name",length=20,unique=true,nullable=false, insertable=true, updatable=true)
    private String name;
    private int age;
    
    /**
     * 枚舉類型:
     * EnumType.STRING: 指定數據庫中存儲的是字符串類型
     * EnumTypee.ORDINAL:指定數據庫 存儲的類型為枚舉的索引
     */
    @Enumerated(EnumType.STRING)
    private Gender gender;
    
    private Double englishScore;
    private Float mathScore;
    
    /**
     * 日期類型: TimeStamp 會根據當地的時間做自動轉換
     * TemporalType.DATE: 指定映射數據庫中的DATE 類型,只存儲日期
     * TemporalType.TIME: 指定映射數據庫 中的TIME類型, 只存儲時間
     * TemporalType.TIMESTAMP:指定映射數據庫中的TIMESTAMP類型
     */
    @Temporal(TemporalType.TIME)
    private Date birthdayTime;
    @Temporal(TemporalType.DATE)
    private Date birthdayDate;
    @Temporal(TemporalType.TIMESTAMP)
    private Date birthday;
    
    @Lob  //大數據文件
    @Basic(fetch=FetchType.LAZY, optional=true)  //延遲加載為true,貌似是Hibernate的一個bug,並不能實現延遲加載
    private byte[] info;
    
    @Transient  //不映射 此字段
    private String transientProperty;
 
    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 int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public Gender getGender() {
        return gender;
    }
 
    public void setGender(Gender gender) {
        this.gender = gender;
    }
 
    public Double getEnglishScore() {
        return englishScore;
    }
 
    public void setEnglishScore(Double englishScore) {
        this.englishScore = englishScore;
    }
 
    public Float getMathScore() {
        return mathScore;
    }
 
    public void setMathScore(Float mathScore) {
        this.mathScore = mathScore;
    }
 
    public Date getBirthdayTime() {
        return birthdayTime;
    }
 
    public void setBirthdayTime(Date birthdayTime) {
        this.birthdayTime = birthdayTime;
    }
 
    public Date getBirthdayDate() {
        return birthdayDate;
    }
 
    public void setBirthdayDate(Date birthdayDate) {
        this.birthdayDate = birthdayDate;
    }
 
    public Date getBirthday() {
        return birthday;
    }
 
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
 
    public byte[] getInfo() {
        return info;
    }
 
    public void setInfo(byte[] info) {
        this.info = info;
    }
 
    public String getTransientProperty() {
        return transientProperty;
    }
 
    public void setTransientProperty(String transientProperty) {
        this.transientProperty = transientProperty;
    }
 
    @Override
    public String toString() {
        return "PersonEntity [id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + ", englishScore=" + englishScore + ", mathScore=" + mathScore + ", birthdayTime=" + birthdayTime + ", birthdayDate=" + birthdayDate + ", birthday=" + birthday + ", transientProperty=" + transientProperty + "]";
    }
    
}

【EntityManger 常用API 使用方法:Test_PersonEntity.java】

package org.zgf.jpa.entity;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
import javax.persistence.Query;
 
import org.junit.Test;
import org.zgf.jpa.enumer.Gender;
/**
 * @Description: 主要測試EntityManager類提供的常用接口
 * @author zonggf
 * @date 2015年11月4日-下午3:38:14
 */
public class Test_PersonEntity extends BasicJPATest {
    
    private PersonEntity getPersonEntity(){
        Date date = new Date();
        PersonEntity person = new PersonEntity();
        person.setName("zhangsan");
        person.setAge(20);
        person.setBirthday(date);
        person.setBirthdayDate(date);
        person.setBirthdayTime(date);
        person.setEnglishScore(20.20);
        person.setMathScore(89.8f);
        person.setGender(Gender.BOY);
        StringBuffer sb = new StringBuffer();
        for(int i=0; i<100;i++){
            sb.append("heladn asndsk nasfjgnas nsd gaksn a sdnkg asdn asndk asnd  ansf asd n  asngjka s");
        }
        person.setInfo(sb.toString().getBytes());
        return person;
    }
    
    //Test API 1: 測試persiste
    @Test
    public void test_persist(){
        PersonEntity personEntity = getPersonEntity();
        this.entityManager.persist(personEntity);
    }
    
    //Test API 2:測試remove接口
    @Test
    public void test_remove_right(){
        //正確刪除方式,必須先從數據庫中查詢,然后再進行刪除,而且查詢結果不能為空
        PersonEntity personEntity = new PersonEntity();
        personEntity.setId(3);
        personEntity = this.entityManager.find(PersonEntity.class, personEntity.getId());
        if(null != personEntity){
            this.entityManager.remove(personEntity);;
        }
    }
    
    //Test API 2:測試remove接口
    @Test(expected=java.lang.IllegalArgumentException.class)
    public void test_remove_wrong(){
        //如果是自己創建的實體 對象,使用remove方式的時候,將會報錯
        PersonEntity personEntity = getPersonEntity();
        personEntity.setId(3);
        this.entityManager.remove(personEntity);;
    }
    
    //Test API 3:測試mege 接口
    @Test
    public void test_merge(){
        //先根據主鍵進行查詢,然后根據主鍵進行更新
        PersonEntity personEntity = getPersonEntity();
        personEntity.setId(7);
        personEntity.setName("zhangsan_merge" + 172);
        this.entityManager.merge(personEntity);
    }
    
    //Test API 4:測試find 接口
    @Test
    public void test_find(){
        //find 方法,是根據主鍵進行查詢的,所以傳的參數必須是主鍵
        int id = 5;
        PersonEntity person = this.entityManager.find(PersonEntity.class, id);
        System.out.println(person);
    }
    
    
    //Test API 5:測試createQuery(String jpql)接口
    @Test
    public void test_createQuery_String(){
        String jpql = "from PersonEntity personEntity";
        Query query = this.entityManager.createQuery(jpql);
        List<PersonEntity> personList = query.getResultList();
        for (PersonEntity personEntity : personList) {
            System.out.println(personEntity);
        }
    }
    
    //Test API 6:測試命名查詢
    @Test
    public void test_namedQuery_jpql(){
        String namedQueryName = "queryByName";
        Query query = this.entityManager.createNamedQuery(namedQueryName);
        //設置命名參數
        query.setParameter("name", "zhangsan");
        PersonEntity person = (PersonEntity) query.getSingleResult();
        System.out.println(person);
    }
    
    //Test API 7:測試createNativeQuery(String sql)接口
    @Test
    public void test_sqlQuery(){
        List<PersonEntity> personList = new ArrayList<>();
        String sql = "select p.id, p.s_name, p.age from tb_person p";
        Query query = this.entityManager.createNativeQuery(sql);
        List list = query.getResultList();
        for(int i=0;i<list.size(); i++){
            PersonEntity person = new PersonEntity();
            Object[] objectArray = (Object[]) list.get(i);
            person.setId((Integer)objectArray[0]);
            person.setName((String)objectArray[1]);
            person.setAge((Integer)objectArray[2]);
            personList.add(person);
        }
        for(PersonEntity personEntity: personList){
            System.out.println(personEntity);
        }
    }
    
    
    
    
    
    
    
}

【輔助類:Gender.java】
package org.zgf.jpa.enumer;
/**
 * @Description: 枚舉類,映射到數據庫中的是BOY 而不是"男"
 * @author zonggf
 * @date 2015年11月4日-下午3:39:36
 */
public enum Gender {
 
    BOY("男"),GIRL("女");
    
    private String gender;
    
    Gender(String gender){
        this.gender = gender;
    }
    
    public static Gender getGender(String gender){
        Gender[] genderEnumers = Gender.values();
        for (Gender genderEnumer : genderEnumers) {
            if(null != gender){
                if(gender.equals(genderEnumer.toString())){
                    return genderEnumer;
                }
            }
        }
        return null;
    }
    
    @Override
    public String toString() {
        return this.gender;
    }
}

【輔助類:BasicJPATest.java】
package org.zgf.jpa.entity;
 
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
 * 這是一個JPA 的測試類,  該類的功能如下:
 * 1. 在每個測試方法之前調用setup 方法,開啟事務並獲取entityManager 對象。
 * 2. 在每個測試方法之后調用teardown 方法, 提交事務,並關閉entityManager 對象
 * @author Silence
 */
public abstract class BasicJPATest {
    protected EntityManagerFactory entityManagerFactory;
    protected EntityManager entityManager;
        
    //子類的每個測試方法之前都會調用
    @Before
    public void setup(){
        this.entityManagerFactory = Persistence.createEntityManagerFactory("myJPA");
        this.entityManager = this.entityManagerFactory.createEntityManager();
        this.entityManager.getTransaction().begin();
    }
    
    //子類的每個測試方法之后都會調用
    @After
    public void tearDown(){
        try{
            this.entityManager.getTransaction().commit();
        }catch(Exception ex){
            System.out.println("提交事務等階段出現了錯誤哦");
        }finally{
            this.entityManager.close();
            this.entityManagerFactory.close();
        }
        
    }
    
    @Test
    public void testCreateTables(){
        System.out.println("數據庫表創建成功。。。");
    }
    
    public void recoverData(){
        //清空表
        String deleteSql = "delete Person";
        Query query = this.entityManager.createQuery(deleteSql);
        query.executeUpdate();
        
    }
}

【注意】
1. @Basic(fetch=FetchType.LAZY) 注解在Hibernate 中不能實現,貌似是Hibernate 的一個bug

2. @Enumerated(EnumType.STRING) 注解映射的是枚舉類的Key ,不是value


免責聲明!

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



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