根据上一篇文章中涉及到的方法进行相关的测试,这里我们需要准备一些测试的持久化类
package com.os.model;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "jpa_teacher")
public class Teacher {
private Integer teacherId;
private String teacherName;
private Integer age;
private String sex;
private Date birthday;
private Date createDate;
@Column(name = "teacher_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
public Integer getTeacherId() {
return teacherId;
}
public void setTeacherId(Integer teacherId) {
this.teacherId = teacherId;
}
@Column(name = "teacher_name",length = 16,nullable = false)
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
this.teacherName = teacherName;
}
@Column(length = 3)
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Column(length = 1)
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Temporal(TemporalType.DATE)
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Column(name = "create_date")
@Temporal(value = TemporalType.TIMESTAMP)
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
@Override
public String toString() {
return "Teacher{" +
"teacherId=" + teacherId +
", teacherName='" + teacherName + '/'' +
", age=" + age +
", sex='" + sex + '/'' +
", birthday=" + birthday +
", createDate=" + createDate +
'}';
}
}
复制代码
数据也准备完毕了,使用程序添加的简单数据
引入单元测试,方便比较学习
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
复制代码
单元测试的基本模版代码如下
package com.os.test;
import org.junit.After;
import org.junit.Before;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JPATest {
private EntityManagerFactory factory ;
private EntityManager entityManager ;
private EntityTransaction tx;
@Before
public void init(){
factory = Persistence.createEntityManagerFactory("jpa02");
entityManager = factory.createEntityManager();
tx = entityManager.getTransaction();
tx.begin();
}
@After
public void close(){
tx.commit();
entityManager.close();
factory.close();
}
}
复制代码
find (Class<T> entityClass,Object primaryKey) :返回指定的 OID 对应的实体类对象,如果这个实体存在于当前的持久化环境,则返回一个被缓存的对象;否则会创建一个新的 Entity, 并加载数据库中相关信息;若 OID 不存在于数据库中,则返回一个 null。第一个参数为被查询的实体类类型,第二个参数为待查找实体的主键值。( 类似于Hibernate中的get方法 )
之后的版本,我们就不在设置粘贴模版代码了,代码如下:
package com.os.test;
import com.os.model.Teacher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JPATest {
private EntityManagerFactory factory ;
private EntityManager entityManager ;
private EntityTransaction tx;
@Before
public void init(){
factory = Persistence.createEntityManagerFactory("jpa02");
entityManager = factory.createEntityManager();
tx = entityManager.getTransaction();
tx.begin();
}
@After
public void close(){
tx.commit();
entityManager.close();
factory.close();
}
//类似于 hibernate 中 Session 的 get 方法.
@Test
public void testFind01(){
Teacher teacher = entityManager.find(Teacher.class,1);//该ID是数据库存在
System.out.println("=========================");
System.out.println(teacher);
}
@Test
public void testFind02(){
Teacher teacher = entityManager.find(Teacher.class,100);//该ID是数据库不存在
System.out.println("=========================");
System.out.println(teacher);
}
}
复制代码
getReference (Class<T> entityClass,Object primaryKey) :与find()方法类似,不同的是:如果缓存中不存在指定的 Entity, EntityManager 会创建一个 Entity 类的代理,但是不会立即加载数据库中的信息,只有 第一次真正使用 此 Entity 的属性才加载,所以如果此 OID 在数据库不存在, getReference() 不会返回 null 值, 而是抛出EntityNotFoundException ( 类似于Hibernate中的load方法 )
//类似于 hibernate 中 Session 的 load 方法
@Test
public void testGetReference01(){
Teacher teacher = entityManager.getReference(Teacher.class,1);//该ID是数据库存在
System.out.println("=========================");
System.out.println(teacher);
}
/**
* javax.persistence.EntityNotFoundException: Unable to find com.os.model.Teacher with id 100
*/
@Test
public void testGetReference02(){
Teacher teacher = entityManager.getReference(Teacher.class,100);//该ID是数据库存在
System.out.println("=========================");
System.out.println(teacher);
}
/**
* org.hibernate.LazyInitializationException: could not initialize proxy [com.os.model.Teacher#1] - no Session
*/
@Test
public void testGetReference03(){
Teacher teacher = entityManager.getReference(Teacher.class,1);//该ID是数据库存在
System.out.println("=========================");
tx.commit();
entityManager.close();
System.out.println(teacher);
}
复制代码
getReference涉及到延迟加载,需要注意EntityManager没有被关闭
为什么使用延迟加载?大家可以执行百度
persist (Object entity) :用于将新创建的Entity纳入到EntityManager的管理。该方法执行后,传入 persist() 方法的 Entity 对象转换成持久化状态。(类似于Hibernate中的save方法)
如果传入 persist() 方法的 Entity 对象已经处于持久化状态,则 persist() 方法什么都不做。
//类似于 hibernate 的 save 方法. 使对象由临时状态变为持久化状态.
//和 hibernate 的 save 方法的不同之处: 若对象有 id, 则不能执行 insert 操作, 而会抛出异常.
@Test
public void testPersist01(){
Teacher teacher = new Teacher();
teacher.setTeacherName("唐僧");
teacher.setAge(99);
teacher.setSex("女");
teacher.setBirthday(new Date());
teacher.setCreateDate(new Date());
entityManager.persist(teacher);//teacher已经处于持久化状态
entityManager.persist(teacher);
entityManager.persist(teacher);
System.out.println(teacher.getTeacherId());
}
复制代码 上述代码说明:我们执行了三次的保存操作,但是我们实际上添加到数据库中记录数为一条,原因就是执行persist方法后,该teacher对象已经处于了持久化状态(在一级缓存中),再次执行 entityManager.persist(teacher); 在一级缓存看看是否存在,如果一致,那么不不执行任何操作
//类似于 hibernate 的 save 方法. 使对象由临时状态变为持久化状态.
//和 hibernate 的 save 方法的不同之处: 若对象有 id, 则不能执行 insert 操作, 而会抛出异常.
@Test
public void testPersist02(){
Teacher teacher = new Teacher();
teacher.setTeacherName("沙僧");
teacher.setAge(99);
teacher.setSex("男");
teacher.setBirthday(new Date());
teacher.setCreateDate(new Date());
entityManager.persist(teacher);//teacher已经处于持久化状态
teacher.setTeacherName("卷帘大将");
System.out.println(teacher.getTeacherId());
}
复制代码 上述代码说明:在事务提交之前,检查一级缓存中存储的对象和实际的对象是否一致,如果不一致会产生Update语句,很重要的
//类似于 hibernate 的 save 方法. 使对象由临时状态变为持久化状态.
//和 hibernate 的 save 方法的不同之处: 若对象有 id, 则不能执行 insert 操作, 而会抛出异常.
/*
* javax.persistence.PersistenceException:
* org.hibernate.PersistentObjectException:
* detached entity passed to persist: com.os.model.Teacher
* */
@Test
public void testPersist03(){
Teacher teacher = new Teacher();
teacher.setTeacherName("悟空");
teacher.setAge(99);
teacher.setSex("男");
teacher.setBirthday(new Date());
teacher.setCreateDate(new Date());
teacher.setTeacherId(88);//注意我设置了主键ID
entityManager.persist(teacher);//teacher已经处于持久化状态
System.out.println(teacher.getTeacherId());
}
复制代码 如果对删除状态的 Entity 进行 persist() 操作,会转换为持久化状态。
@Test
public void testPersist04(){
Teacher teacher = entityManager.find(Teacher.class,5);//1.持久化状态
entityManager.remove(teacher);
System.out.println("teacher = " + teacher);//2.处于删除状态
entityManager.persist(teacher);//3.处于游离状态
}
复制代码 上述代码说明:其实根本就没有产生delete语句,只有一个查询操作,因为上述代码给人的感觉“ 还原 ”
如果对游离状态的实体执行 persist() 操作,可能会在 persist() 方法抛出 EntityExistException(也有可能是在flush或事务提交后抛出)。
@Test
public void testPersist05(){
Teacher teacher = entityManager.find(Teacher.class,5);//1.持久化状状态
tx.commit();
entityManager.close();
System.out.println("teacher = " + teacher);//2.处于游离状态
entityManager = factory.createEntityManager();
tx = entityManager.getTransaction();
tx.begin();
entityManager.persist(teacher);
/*
*javax.persistence.PersistenceException:
* org.hibernate.PersistentObjectException:
* detached entity passed to persist: com.os.model.Teacher
* */
}
复制代码 remove (Object entity) :删除实例。如果实例是被管理的,即与数据库实体记录关联,则同时会删除关联的数据库记录。(类似于Hibernate中的Delete方法)
//类似于 hibernate 中 Session 的 delete 方法. 把对象对应的记录从数据库中移除
//但注意: 该方法只能移除 持久化 对象. 而 hibernate 的 delete 方法实际上还可以移除 游离对象.
@Test
public void testRemove01(){
Teacher teacher = new Teacher();//瞬时状态
teacher.setTeacherId(4);//数据库中存在该条记录
entityManager.remove(teacher);
/*
* java.lang.IllegalArgumentException:
* Removing a detached instance com.os.model.Teacher#4
* */
}
复制代码
//类似于 hibernate 中 Session 的 delete 方法. 把对象对应的记录从数据库中移除
//但注意: 该方法只能移除 持久化 对象. 而 hibernate 的 delete 方法实际上还可以移除 游离对象.
@Test
public void testRemove02(){
Teacher teacher = entityManager.getReference(Teacher.class,4);//持久化对象
entityManager.remove(teacher);//使用的时候先查询后执行删除操作
}
复制代码
merge (T entity) :merge() 用于处理 Entity 的同步。即数据库的插入和更新操作,这个操作的情况有点多,我们通过代码进行说明
/*
* 若传入的是一个临时对象
* 会创建一个新的对象, 把临时对象的属性复制到新的对象中, 然后对新的对象执行持久化操作. 所以
* 新的对象中有 id, 但以前的临时对象中没有 id.
* */
@Test
public void testMerge1(){
Teacher teacher = new Teacher();
teacher.setTeacherName("林黛玉");
teacher.setAge(19);
teacher.setSex("女");
teacher.setBirthday(new Date());
teacher.setCreateDate(new Date());
Teacher teacher1 = entityManager.merge(teacher);
System.out.println("teacher.getTeacherId() = " + teacher.getTeacherId());
System.out.println("teacher1.getTeacherId() = " + teacher1.getTeacherId());
}
复制代码
@Test
public void testMerge2(){
Teacher teacher = new Teacher();
teacher.setTeacherName("林黛玉");
teacher.setAge(19);
teacher.setSex("女");
teacher.setBirthday(new Date());
teacher.setCreateDate(new Date());
teacher.setTeacherId(100);//数据库没有该主键ID
Teacher teacher1 = entityManager.merge(teacher);
System.out.println("teacher.getTeacherId() = " + teacher.getTeacherId());
System.out.println("teacher1.getTeacherId() = " + teacher1.getTeacherId());
}
复制代码
@Test
public void testMerge3(){
Teacher teacher = new Teacher();
teacher.setTeacherName("林黛玉");
teacher.setAge(19);
teacher.setSex("女");
teacher.setBirthday(new Date());
teacher.setCreateDate(new Date());
teacher.setTeacherId(5);//数据库有该主键ID
Teacher teacher1 = entityManager.merge(teacher);
System.out.println("teacher.getTeacherId() = " + teacher.getTeacherId());
System.out.println("teacher1.getTeacherId() = " + teacher1.getTeacherId());
}
复制代码
@Test
public void testMerge4(){
Teacher teacher = new Teacher();
teacher.setTeacherName("林黛玉");
teacher.setAge(19);
teacher.setSex("女");
teacher.setBirthday(new Date());
teacher.setCreateDate(new Date());
teacher.setTeacherId(7);//数据库有该主键ID
System.out.println("teacher = " + teacher);
Teacher teacher1 = entityManager.find(Teacher.class,7);//一级缓存中存在该对象
System.out.println("teacher1 = " + teacher1);
entityManager.merge(teacher);
System.out.println(teacher==teacher1);//返回的是false
}
复制代码
flush () :同步持久上下文环境,即将持久上下文环境的所有未保存实体的状态信息保存到数据库中
这里需要使用断点调试,断点设置如图
@Test
public void testFlush(){
Teacher teacher = entityManager.find(Teacher.class,1);
System.out.println("teacher = " + teacher);
teacher.setTeacherName("林冲");
entityManager.flush();
}
复制代码
refresh (Object entity) :用数据库实体记录的值更新实体对象的状态,即更新实例的属性值。
@Test
public void testReflush(){
Teacher teacher = entityManager.find(Teacher.class,1);
System.out.println("teacher = " + teacher);
teacher = entityManager.find(Teacher.class,1);
entityManager.refresh(teacher);//重新进行查询操作
}
复制代码