1 JPA状态转换图
要理解JPA的核心接口,这个图必须牢记。
分为4种状态:
1)New状态:未有id,未与Persistence Context建立关联关系。
2)Managed状态:有id,已经与Persistence Context建立了关联关系。
3)Detached状态,有id,但未与Persistence Context建立关联关系。
4)Removed状态,有id,与Persistence Context仍有关联关系,但是正准备从数据库中删除。
区分New和Detached状态:
也就是说如果你Course course = new Course();course.setName("New state");就处于New状态。
如果Course course = new Course();course.setId(1);couse.setName("Detached state");就处于Detached状态。
New状态也可以执行merge()方法,会生成一个insert 语句,并且会生成一个新的对象。
Detached状态的执行merge()方法,也会生成一个新的对象,并且视对应的id在数据库中存不存在来决定执行insert操作(不存在时)还是执行update操作(存在时)。
对比一下Hibernate的3种状态:
JPA跟Hibernate很相似,只是多了Removed状态,接口更简洁一些。
2 具体例子
各种状态对应的测试方法,见方法注释。
JpaUtil 及配置文件的代码参见:《JPA之HelloWorld(一)》
public class JpaStateMain {
private static EntityManager em ;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
em = JpaUtil.currentManager();
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
JpaUtil.closeManager();
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
/**
* new状态执行persist,转换成managed状态,执行insert
*/
@Test
public void persist1() {
em.getTransaction().begin();
Course course = new Course();
course.setName("english");
try {
em.persist(course); //对应hibernate session.save(course);
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* detached状态执行persist,抛异常 javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persis
*/
@Test
public void persist2() {
em.getTransaction().begin();
Course course = new Course();
course.setId(40);
course.setName("english");
try {
em.persist(course);
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* persist状态执行persist,不起作用
*/
@Test
public void persist3() {
em.getTransaction().begin();
Course course = new Course();
// course.setId(40);
course.setName("persist3");
try {
em.persist(course);
em.persist(course);
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* persist状态执行persist,不起作用
*/
@Test
public void persist4() {
em.getTransaction().begin();
Course course = em.getReference(Course.class,40);
// course.setId(40);
course.setName("persist4");
try {
em.persist(course);//执不执行结果都一样
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* remove状态执行persist,抛异常org.hibernate.AssertionFailure: Unable to perform un-delete for instance
*/
@Test
public void persist5() {
em.getTransaction().begin();
Course course = em.getReference(Course.class,41);
course.setName("persist5");
try {
em.remove(course);
em.persist(course);
// course.setName("afterremove");
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* getReference获取的对象处于managed状态
*/
@Test
public void getReference() {
em.getTransaction().begin();
Course course = em.getReference(Course.class,44);
course.setName("getrefernce");
try {
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* find获取的对象也处于managed状态
*/
@Test
public void find() {
em.getTransaction().begin();
Course course = em.find(Course.class,45);
course.setName("find");
try {
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* new状态的执行remove,什么都不执行。
*/
@Test
public void remove1() {
Course course = new Course();
course.setName("remove");
em.getTransaction().begin();
try {
em.remove(course);
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* managed状态的执行remove,删除。
*/
@Test
public void remove2() {
em.getTransaction().begin();
Course course = em.find(Course.class,44);
try {
em.remove(course);
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* detached状态的执行remove,抛异常java.lang.IllegalArgumentException: Removing a detached instance
*/
@Test
public void remove3() {
Course course = new Course();
course.setId(43);
course.setName("remove3");
em.getTransaction().begin();
try {
em.remove(course);
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* remove状态的执行remove,不起作用。
*/
@Test
public void remove4() {
em.getTransaction().begin();
Course course = em.find(Course.class,43);
try {
em.remove(course);
em.remove(course);
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* new状态执行merge,生成一个新的对象,执行insert语句
*/
@Test
public void merge1() {
Course course = new Course();
course.setName("merge1");
em.getTransaction().begin();
try {
Course course2 = em.merge(course);
course2.setName("aftermerge");
// course.setName("aftercourse");//没有作用
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* detached状态执行merge,变为managed状态,生成一个新的对象,
* course2.setname 起作用执行update, couse.setname不起作用,原来的course仍然处于detached状态
* course.setId(77);数据库中不存在记录,merge后,执行insert,id按自增生成,而不是set的77
* course.setId(49);数据库中存在记录,merge不执行insert,执行update,如果setname的值跟数据中也一样,则什么都不执行。
*/
@Test
public void merge2() {
Course course = new Course();
course.setId(52);
course.setName("merge52");
em.getTransaction().begin();
try {
Course course2 = em.merge(course);
// course2.setName("aftermerge");
// course.setName("aftercourse");
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* managed状态执行merge,状态不变。不生成新的对象。
* course 和course2指向同一个对象
*/
@Test
public void merge3() {
em.getTransaction().begin();
Course course = em.find(Course.class,48);
try {
Course course2 = em.merge(course);
course.setName("mergecourse");
course2.setName("merge3");
System.out.print(course == course2);
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
/**
* removed状态不允许执行merge,抛异常java.lang.IllegalArgumentException: org.hibernate.ObjectDeletedException: deleted instance passed to merge:
*/
@Test
public void merge4() {
em.getTransaction().begin();
Course course = em.find(Course.class,48);
try {
em.remove(course);
em.merge(course);
em.getTransaction().commit();
}catch (Exception e){
e.printStackTrace();
em.getTransaction().rollback();
}
}
}