侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

【JPA专题】05.JPA的基本操作CRUD

2022-06-12 星期日 / 0 评论 / 0 点赞 / 76 阅读 / 31211 字

基本操作CRUD根据上一篇文章中涉及到的方法进行相关的测试,这里我们需要准备一些测试的持久化类老师基本信息持久化类:package com.os.model;import javax.persiste

基本操作CRUD

根据上一篇文章中涉及到的方法进行相关的测试,这里我们需要准备一些测试的持久化类

老师基本信息持久化类:

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 和 getReference 区别

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 方法@Testpublic 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  */@Testpublic 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*/@Testpublic 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 操作, 而会抛出异常.@Testpublic 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() 操作,会转换为持久化状态。

    @Testpublic 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或事务提交后抛出)。

    @Testpublic 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 方法实际上还可以移除 游离对象.@Testpublic 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 方法实际上还可以移除 游离对象.@Testpublic void testRemove02(){    Teacher teacher = entityManager.getReference(Teacher.class,4);//持久化对象    entityManager.remove(teacher);//使用的时候先查询后执行删除操作}

merge (T entity):merge() 用于处理 Entity 的同步。即数据库的插入和更新操作,这个操作的情况有点多,我们通过代码进行说明

总的来说: 类似于 hibernate Session 的 saveOrUpdate 方法.

1.临时对象,执行保存操作

/* * 若传入的是一个临时对象 * 会创建一个新的对象, 把临时对象的属性复制到新的对象中, 然后对新的对象执行持久化操作. 所以 * 新的对象中有 id, 但以前的临时对象中没有 id. * */@Testpublic 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());}

2. 若传入的是一个游离对象,若在 EntityManager 缓存中没有该对象, 即传入的对象有 OID,数据库中没有对应的主键ID

执行Insert操作,老对象的teacherId是100,保存之后新对象的主键ID是数据库中的主键ID

@Testpublic 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());}

3. 若传入的是一个游离对象,若在 EntityManager 缓存中没有该对象, 即传入的对象有 OID,数据库中有对应的主键ID

JPA 会查询对应的记录, 然后返回该记录对一个的对象, 再然后会把游离对象的属性复制到查询到的对象中,执行Update操作

@Testpublic 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());}

4. 若传入的是一个游离对象,若在 EntityManager 缓存中有该对象, 即传入的对象有 OID,数据库中有对应的主键ID

JPA 会把游离对象的属性复制到查询到EntityManager 缓存中的对象中,EntityManager 缓存中的对象执行 UPDATE

@Testpublic 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 ():同步持久上下文环境,即将持久上下文环境的所有未保存实体的状态信息保存到数据库中

这里需要使用断点调试,断点设置如图

@Testpublic void testFlush(){    Teacher teacher = entityManager.find(Teacher.class,1);    System.out.println("teacher = " + teacher);    teacher.setTeacherName("林冲");    entityManager.flush();}

refresh (Object entity):用数据库实体记录的值更新实体对象的状态,即更新实例的属性值。

@Testpublic void testReflush(){    Teacher teacher = entityManager.find(Teacher.class,1);    System.out.println("teacher = " + teacher);    teacher = entityManager.find(Teacher.class,1);    entityManager.refresh(teacher);//重新进行查询操作}
.
.

广告 广告

评论区