JPA 学习篇(三)简单实体映射和EntityManagerAPI

来源:互联网 发布:网络诈骗了2000要判刑 编辑:程序博客网 时间:2024/06/07 12:01

【常用注解】

使用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;}@Overridepublic 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@Testpublic void test_persist(){PersonEntity personEntity = getPersonEntity();this.entityManager.persist(personEntity);}//Test API 2:测试remove接口@Testpublic 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 接口@Testpublic void test_merge(){//先根据主键进行查询,然后根据主键进行更新PersonEntity personEntity = getPersonEntity();personEntity.setId(7);personEntity.setName("zhangsan_merge" + 172);this.entityManager.merge(personEntity);}//Test API 4:测试find 接口@Testpublic 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)接口@Testpublic 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:测试命名查询@Testpublic 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)接口@Testpublic 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;}@Overridepublic 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;//子类的每个测试方法之前都会调用@Beforepublic void setup(){this.entityManagerFactory = Persistence.createEntityManagerFactory("myJPA");this.entityManager = this.entityManagerFactory.createEntityManager();this.entityManager.getTransaction().begin();}//子类的每个测试方法之后都会调用@Afterpublic void tearDown(){try{this.entityManager.getTransaction().commit();}catch(Exception ex){System.out.println("提交事务等阶段出现了错误哦");}finally{this.entityManager.close();this.entityManagerFactory.close();}}@Testpublic 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


3. 源代码下载:【D_JPA_03_简单实体映射和API.zip】





0 0
原创粉丝点击