JPA 相关API (一)
2021-02-17 05:20
1. JPA 中sql 语句设置参数有两种形式,一种是命名参数,另一种是位置参数:
位置参数:执行效率高, 可读性差,可用于原生sql 和 JPQL 语句中, 格式《?+数字》,数字可任意指定 也可以不指定,直接用问号
命名参数:执行效率低 ,可读性强,可用于原生sql 和 JPQL 语句中, 格式《:+ 名称》,名称自定义
2. query.getSigleResult(); 方法必须确保查询结果有且只有一个放回对象。
3. query.excuteUpdate();方法可用于执行更新,删除语句
简单实体映射和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 语句。
【简单实体对象:PersonEntity.java】
1 package org.zgf.jpa.entity; 2 3 import java.util.Date; 4 5 import javax.persistence.Basic; 6 import javax.persistence.Column; 7 import javax.persistence.Entity; 8 import javax.persistence.EnumType; 9 import javax.persistence.Enumerated; 10 import javax.persistence.FetchType; 11 import javax.persistence.GeneratedValue; 12 import javax.persistence.GenerationType; 13 import javax.persistence.Id; 14 import javax.persistence.Lob; 15 import javax.persistence.NamedQueries; 16 import javax.persistence.NamedQuery; 17 import javax.persistence.Table; 18 import javax.persistence.Temporal; 19 import javax.persistence.TemporalType; 20 import javax.persistence.Transient; 21 22 import org.zgf.jpa.enumer.Gender; 23 24 25 26 @Table(name="tb_person") 27 @Entity 28 @NamedQueries({ //命名查询注解:只能写JPQL 语句 29 @NamedQuery(name="queryAllByJpql",query="from PersonEntity personEntity"), 30 @NamedQuery(name="queryByName",query="from PersonEntity personEntity where personEntity.name = :name") 31 }) 32 public class PersonEntity { 33 34 /** 35 * 测试主键生成策略 36 * GenerationType.AUTO: 根据数据库的默认规则来生成主键 37 * GenerationType.IDENTITY:数据库自增(mysql 适用,Oracle不适用) 38 * GenerationType.SEQUENCE:序列生成方式,(Oracle适用,mysql 不适用) 39 */ 40 @Id 41 @GeneratedValue(strategy=GenerationType.AUTO) 42 private Integer id; 43 44 /*** 45 * 数据库字段限制: 46 * Column可以指定数据库 字段的名称 ,长度,唯一性,是否可以为空,是否可以插入,是否可以更新 47 */ 48 @Column(name="s_name",length=20,unique=true,nullable=false, insertable=true, updatable=true) 49 private String name; 50 private int age; 51 52 /** 53 * 枚举类型: 54 * EnumType.STRING: 指定数据库中存储的是字符串类型 55 * EnumTypee.ORDINAL:指定数据库 存储的类型为枚举的索引 56 */ 57 @Enumerated(EnumType.STRING) 58 private Gender gender; 59 60 private Double englishScore; 61 private Float mathScore; 62 63 /** 64 * 日期类型: TimeStamp 会根据当地的时间做自动转换 65 * TemporalType.DATE: 指定映射数据库中的DATE 类型,只存储日期 66 * TemporalType.TIME: 指定映射数据库 中的TIME类型, 只存储时间 67 * TemporalType.TIMESTAMP:指定映射数据库中的TIMESTAMP类型 68 */ 69 @Temporal(TemporalType.TIME) 70 private Date birthdayTime; 71 @Temporal(TemporalType.DATE) 72 private Date birthdayDate; 73 @Temporal(TemporalType.TIMESTAMP) 74 private Date birthday; 75 76 @Lob //大数据文件 77 @Basic(fetch=FetchType.LAZY, optional=true) //延迟加载为true,貌似是Hibernate的一个bug,并不能实现延迟加载 78 private byte[] info; 79 80 @Transient //不映射 此字段 81 private String transientProperty; 82 83 public Integer getId() { 84 return id; 85 } 86 87 public void setId(Integer id) { 88 this.id = id; 89 } 90 91 public String getName() { 92 return name; 93 } 94 95 public void setName(String name) { 96 this.name = name; 97 } 98 99 public int getAge() { 100 return age; 101 } 102 103 public void setAge(int age) { 104 this.age = age; 105 } 106 107 public Gender getGender() { 108 return gender; 109 } 110 111 public void setGender(Gender gender) { 112 this.gender = gender; 113 } 114 115 public Double getEnglishScore() { 116 return englishScore; 117 } 118 119 public void setEnglishScore(Double englishScore) { 120 this.englishScore = englishScore; 121 } 122 123 public Float getMathScore() { 124 return mathScore; 125 } 126 127 public void setMathScore(Float mathScore) { 128 this.mathScore = mathScore; 129 } 130 131 public Date getBirthdayTime() { 132 return birthdayTime; 133 } 134 135 public void setBirthdayTime(Date birthdayTime) { 136 this.birthdayTime = birthdayTime; 137 } 138 139 public Date getBirthdayDate() { 140 return birthdayDate; 141 } 142 143 public void setBirthdayDate(Date birthdayDate) { 144 this.birthdayDate = birthdayDate; 145 } 146 147 public Date getBirthday() { 148 return birthday; 149 } 150 151 public void setBirthday(Date birthday) { 152 this.birthday = birthday; 153 } 154 155 public byte[] getInfo() { 156 return info; 157 } 158 159 public void setInfo(byte[] info) { 160 this.info = info; 161 } 162 163 public String getTransientProperty() { 164 return transientProperty; 165 } 166 167 public void setTransientProperty(String transientProperty) { 168 this.transientProperty = transientProperty; 169 } 175 176 }
【EntityManger 常用API 使用方法:Test_PersonEntity.java】
1 package org.zgf.jpa.entity; 2 3 import java.util.ArrayList; 4 import java.util.Date; 5 import java.util.List; 6 7 import javax.persistence.Query; 8 9 import org.junit.Test; 10 import org.zgf.jpa.enumer.Gender; 11 /** 12 * @Description: 主要测试EntityManager类提供的常用接口 13 * @author zonggf 14 * @date 2015年11月4日-下午3:38:14 15 */ 16 public class Test_PersonEntity extends BasicJPATest { 17 18 private PersonEntity getPersonEntity(){ 19 Date date = new Date(); 20 PersonEntity person = new PersonEntity(); 21 person.setName("zhangsan"); 22 person.setAge(20); 23 person.setBirthday(date); 24 person.setBirthdayDate(date); 25 person.setBirthdayTime(date); 26 person.setEnglishScore(20.20); 27 person.setMathScore(89.8f); 28 person.setGender(Gender.BOY); 29 StringBuffer sb = new StringBuffer(); 30 for(int i=0; i){ 31 sb.append("heladn asndsk nasfjgnas nsd gaksn a sdnkg asdn asndk asnd ansf asd n asngjka s"); 32 } 33 person.setInfo(sb.toString().getBytes()); 34 return person; 35 } 36 37 //Test API 1: 测试persiste 38 @Test 39 public void test_persist(){ 40 PersonEntity personEntity = getPersonEntity(); 41 this.entityManager.persist(personEntity); 42 } 43 44 //Test API 2:测试remove接口 45 @Test 46 public void test_remove_right(){ 47 //正确删除方式,必须先从数据库中查询,然后再进行删除,而且查询结果不能为空 48 PersonEntity personEntity = new PersonEntity(); 49 personEntity.setId(3); 50 personEntity = this.entityManager.find(PersonEntity.class, personEntity.getId()); 51 if(null != personEntity){ 52 this.entityManager.remove(personEntity);; 53 } 54 } 55 56 //Test API 2:测试remove接口 57 @Test(expected=java.lang.IllegalArgumentException.class) 58 public void test_remove_wrong(){ 59 //如果是自己创建的实体 对象,使用remove方式的时候,将会报错 60 PersonEntity personEntity = getPersonEntity(); 61 personEntity.setId(3); 62 this.entityManager.remove(personEntity);; 63 } 64 65 //Test API 3:测试mege 接口 66 @Test 67 public void test_merge(){ 68 //先根据主键进行查询,然后根据主键进行更新 69 PersonEntity personEntity = getPersonEntity(); 70 personEntity.setId(7); 71 personEntity.setName("zhangsan_merge" + 172); 72 this.entityManager.merge(personEntity); 73 } 74 75 //Test API 4:测试find 接口 76 @Test 77 public void test_find(){ 78 //find 方法,是根据主键进行查询的,所以传的参数必须是主键 79 int id = 5; 80 PersonEntity person = this.entityManager.find(PersonEntity.class, id); 81 System.out.println(person); 82 } 83 84 85 //Test API 5:测试createQuery(String jpql)接口 86 @Test 87 public void test_createQuery_String(){ 88 String jpql = "from PersonEntity personEntity"; 89 Query query = this.entityManager.createQuery(jpql); 90 ListpersonList = query.getResultList(); 91 for (PersonEntity personEntity : personList) { 92 System.out.println(personEntity); 93 } 94 } 95 96 //Test API 6:测试命名查询 97 @Test 98 public void test_namedQuery_jpql(){ 99 String namedQueryName = "queryByName"; 100 Query query = this.entityManager.createNamedQuery(namedQueryName); 101 //设置命名参数 102 query.setParameter("name", "zhangsan"); 103 PersonEntity person = (PersonEntity) query.getSingleResult(); 104 System.out.println(person); 105 } 106 107 //Test API 7:测试createNativeQuery(String sql)接口 108 @Test 109 public void test_sqlQuery(){ 110 List personList = new ArrayList(); 111 String sql = "select p.id, p.s_name, p.age from tb_person p"; 112 Query query = this.entityManager.createNativeQuery(sql); 113 List list = query.getResultList(); 114 for(int i=0;i ){ 115 PersonEntity person = new PersonEntity(); 116 Object[] objectArray = (Object[]) list.get(i); 117 person.setId((Integer)objectArray[0]); 118 person.setName((String)objectArray[1]); 119 person.setAge((Integer)objectArray[2]); 120 personList.add(person); 121 } 122 for(PersonEntity personEntity: personList){ 123 System.out.println(personEntity); 124 } 125 } 126 }
【辅助类:Gender.java】
1 package org.zgf.jpa.enumer; 2 /** 3 * @Description: 枚举类,映射到数据库中的是BOY 而不是"男" 4 * @author zonggf 5 * @date 2015年11月4日-下午3:39:36 6 */ 7 public enum Gender { 8 9 BOY("男"),GIRL("女"); 10 11 private String gender; 12 13 Gender(String gender){ 14 this.gender = gender; 15 } 16 17 public static Gender getGender(String gender){ 18 Gender[] genderEnumers = Gender.values(); 19 for (Gender genderEnumer : genderEnumers) { 20 if(null != gender){ 21 if(gender.equals(genderEnumer.toString())){ 22 return genderEnumer; 23 } 24 } 25 } 26 return null; 27 } 28 29 @Override 30 public String toString() { 31 return this.gender; 32 } 33 }
【辅助类:BasicJPATest.java】
1 package org.zgf.jpa.entity; 2 3 4 import javax.persistence.EntityManager; 5 import javax.persistence.EntityManagerFactory; 6 import javax.persistence.Persistence; 7 import javax.persistence.Query; 8 9 import org.junit.After; 10 import org.junit.Before; 11 import org.junit.Test; 12 /** 13 * 这是一个JPA 的测试类, 该类的功能如下: 14 * 1. 在每个测试方法之前调用setup 方法,开启事务并获取entityManager 对象。 15 * 2. 在每个测试方法之后调用teardown 方法, 提交事务,并关闭entityManager 对象 16 * @author Silence 17 */ 18 public abstract class BasicJPATest { 19 protected EntityManagerFactory entityManagerFactory; 20 protected EntityManager entityManager; 21 22 //子类的每个测试方法之前都会调用 23 @Before 24 public void setup(){ 25 this.entityManagerFactory = Persistence.createEntityManagerFactory("myJPA"); 26 this.entityManager = this.entityManagerFactory.createEntityManager(); 27 this.entityManager.getTransaction().begin(); 28 } 29 30 //子类的每个测试方法之后都会调用 31 @After 32 public void tearDown(){ 33 try{ 34 this.entityManager.getTransaction().commit(); 35 }catch(Exception ex){ 36 System.out.println("提交事务等阶段出现了错误哦"); 37 }finally{ 38 this.entityManager.close(); 39 this.entityManagerFactory.close(); 40 } 41 42 } 43 44 @Test 45 public void testCreateTables(){ 46 System.out.println("数据库表创建成功。。。"); 47 } 48 49 public void recoverData(){ 50 //清空表 51 String deleteSql = "delete Person"; 52 Query query = this.entityManager.createQuery(deleteSql); 53 query.executeUpdate(); 54 55 } 56 }
【注意】
1. @Basic(fetch=FetchType.LAZY) 注解在Hibernate 中不能实现,貌似是Hibernate 的一个bug
2. @Enumerated(EnumType.STRING) 注解映射的是枚举类的Key ,不是value
上一篇:win10 uwp 商业游戏