07、应用JPA加载_更新_删除对象

07、使用JPA加载_更新_删除对象

 

PersonTest.java

package junit.test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.junit.BeforeClass;
import org.junit.Test;

import cn.itcast.bean.Person;

public class PersonTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@Test public void save(){
		//对实体bean进行操作,第一步应该获取什么对象啊?     SessionFactory对象。
		//这里用获取的EntityManagerFactory对象,这可以把它看成跟Hibernate的SessionFactory对象差不多的东西。
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();//开启事务
		em.persist(new Person("传智播客"));
		em.getTransaction().commit();
		em.close();
		factory.close();

		//SessionFactory  -->  Session  -->  begin事务
	}
	/*
session.save(obj);
    persist这方法在Hibernate里也存在,Hibernate的作者已经不太推荐大家用save方法,而是推荐大家用persist方法。
    why? 首先并不是代码上的问题,主要是这个名字上的问题,因为我们把这个ORM技术叫做持久化产品,那么我们对某个对象持久化,应该叫持久化,而不应该叫保存,所以后来Hibernate的作者推荐用persist方法,这并不是功能的问题,主要是取名的问题,所以用persist方法也可以。
	 */

	@Test public void getPerson(){
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
		EntityManager em = factory.createEntityManager();
		Person person = em.find(Person.class,1);	//相当于Hibernate的get方法,与load方法对应,不延迟加载。
		System.out.println(person.getName());
		em.close();
		factory.close();
	}

	@Test public void getPerson2(){
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
		EntityManager em = factory.createEntityManager();
		Person person = em.getReference(Person.class,1);
        //相当于Hibernate的load方法,延迟加载。
		//并不会立刻从数据库里面得到这条记录,只是返回了一个代理对象。
		System.out.println(person.getName());
        //这时候才会去数据库里得数据,发生加载行为。
		//这时候要确保实体管理器处于打开状态。
		em.close();
		//System.out.println(person.getName()); 如果屏蔽上上句,在这里才访问属性,那就会出错,延迟加载需要EntityManager没关闭,实际是hibernate的session没关闭。
		factory.close();
	}
   
    //jpa实体的四种状态:
	/*(1)new 新建状态。刚new出来的实体bean没有与任何EntityManager相关联就是新建状态。
	  (2)managed 托管状态(与EntityManager相关联,被EntityManager托管),用EntityManager的find和getReference方法查找出来的对象就是一个托管状态bean。
	  (3)游离状态。EntityManager对象调用clear方法,就把这个对象所托管的所有对象都变成游离状态的对象了。保存更改了处于游离状态的bean需要调用EntityManager对象的merge方法。
	  (4)删除状态。*/

	@Test public void updatePerson(){   //更改数据库里标志为1的那条记录的名字为老张,更改成功的两个条件:1、必须开启事务;2、这个bean对象处于托管状态。
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin(); //开启事务,只读取数据不需要开事务,更改数据的时候需要开事务。
		Person person=em.find(Person.class,1); //相当于Hibernate的get方法,第一个参数是实体Bean类(get方法采用泛型)(传什么类的class对象进去就返回什么类的对象回来),第二个参数是实体bean标识符的值(即ID的值,传入哪个id值返回的就是id为那个值的那条记录)。
		person.setName("老张");  //这个person是处于一个托管状态的bean对象,用set方法改变的属性并不会马上更新到数据库里面去,而是把这个操作放在一个jdbc的批处理里面,等到事务提交的时候才会更新到数据库里面去。
		em.getTransaction().commit();
		em.close();
		factory.close();
	}

	@Test public void updatePerson2(){
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();	//开启事务。
		Person person=em.find(Person.class,1);
		em.clear();	//把实体管理器中的所有实体变成游离状态。
		person.setName("老黎");
		em.merge(person);    //更新处于游离状态的bean对象。
		em.getTransaction().commit();
		em.close();
		factory.close();
	}

	@Test public void delete(){
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();	//开启事务。
		Person person=em.find(Person.class,1);
		em.remove(person);    //删除的bean对象也必须是处于托管状态的对象才能被删除成功。否则,如果person不是托管状态的bean,也不会报错但数据库内的数据也不会删除。
		em.getTransaction().commit();
		em.close();
		factory.close();
	}

}

 

 



     我们目前使用的是Hibernate,实际上我们操纵EntityManager对象时,它内部是操纵了Hibernate里面的sesson对象。它内部只是对session对象做了个封装而已。

 

   	@Test public void getPerson(){
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
		EntityManager em = factory.createEntityManager();
		Person person = em.find(Person.class,2);	//相当于Hibernate的get方法。
		System.out.println(person);
		em.close();
		factory.close();
	}

 

如果不存在id为2的person的话,那么返回的是null值 。

	@Test public void getPerson2(){
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
		EntityManager em = factory.createEntityManager();
		Person person = em.getReference(Person.class,2);     //1
		System.out.println(person);                          //2
		em.close();
		factory.close();
	}

 



    如果不存在id为2的person的话,那么返回的是异常(javax.persistence.EntityNotFoundException)。
    异常是在什么时候触发的呢? 是在1?还是2呢?
    答案是2。这说明并不是em.getReference()这个方法执行时就发生异常,而是在你访问这个对象或是它属性的时候才出现异常。

    数据库里没有相应的记录,EntityManagerd对象的get方法获取不到记录会返回null,而EntityManagerd对象的getReference方法获取不到记录会在下一次访问这个返回值的时候抛出异常。 

	@Test public void updatePerson2(){
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();//开启事务。
		Person person=em.find(Person.class,1);
		em.clear();  //把实体管理器中的所有实体变成游离状态。
		person.setName("老黎");
		em.getTransaction().commit();
		em.close();
		factory.close();
	}

 

    在clear之后,person变成了游离状态,这时候对游离状态的实体进行更新的话(person.setName("老黎");),更新的数据是不能同步到数据库的。可以采用方法em.merge(person);这方法是用于把在游离状态时候的更新同步到数据库。