JPA 学习篇(三)简单实体映射和EntityManagerAPI
2015-11-04 15:15
591 查看
【常用注解】
使用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】
【EntityManger 常用API 使用方法:Test_PersonEntity.java】
【辅助类:Gender.java】
【辅助类:BasicJPATest.java】
【注意】
1. @Basic(fetch=FetchType.LAZY) 注解在Hibernate 中不能实现,貌似是Hibernate 的一个bug
2. @Enumerated(EnumType.STRING) 注解映射的是枚举类的Key ,不是value
3. 源代码下载:【D_JPA_03_简单实体映射和API.zip】
使用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
3. 源代码下载:【D_JPA_03_简单实体映射和API.zip】
相关文章推荐
- Efs Frame企业级开发框架源码
- php开发工具zendstudio13破解补丁
- 巧用JSON.stringify()生成漂亮格式的JSON字符串
- 通俗易懂理解 隐马尔可夫(HMM)
- SQL Server 2008R2 数据库邮件
- [Leetcode]H-Index II
- 使用ST TOOLS的STVP烧写程序快速入门
- Editor——(AddChild、AddParent)
- 微信公众号开发sprintf()函数其中%S等符号的说明
- Android源码编译
- Oracle Linux配置Yum的repo
- 矢量叉积判断顺时针还是逆时针
- NOI题库192 生日蛋糕
- 如何使用JVisualVM进行性能分析
- 你应该成为 Web 开发者的 5 大理由—兄弟连IT教育
- CentOS 下对 Nginx + Tomcat 配置 SSL 实现服务器 / 客户端双向认证
- CentOS6.5最小化安装包选择
- 数据结构与算法
- iOS学习之OC语法基础-类和对象-什么是类
- Python变量类型