`
lovethisworld
  • 浏览: 52633 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JPA实体状态&联级操作

    博客分类:
  • JPA
阅读更多

JPA的实体具有四种状态,如图所示:

 

  • 新实体(new)Entity由应用产生,和EJB3 Persistence运行环境没有联系,也没有唯一的标示符(Identity)
  • 持久化实体(managed)。新实体和EJB3 Persistence运行环境产生关联(通过persist(), merge()等方法),在EJB3 Persistence运行环境中存在和被管理,标志是在EJB3 Persistence运行环境中有一个唯一的标示(Identity)
  • 分离的实体(detached)Entity有唯一标示符,但它的标示符不被EJB3 Persistence运行环境管理, 同样的该Entity也不被EJB3 Persistence运行环境管理。
  • 删除的实体(removed)Entityremove()方法删除,对应的纪录将会在当前事务提交的时候从数据库中删除。
接下来动手测试下实体状态:
  • 构建实体类:Parent和Child
@Entity
public class Parent {

	@Id @GeneratedValue
	private int id;
	
        //定义了5中不同的联级类型,all表示包含四种类型
	@OneToOne(cascade=CascadeType.PERSIST)
	private Child persist;

	@OneToOne(cascade=CascadeType.REMOVE)
	private Child remove;

	@OneToOne(cascade=CascadeType.MERGE)
	private Child merge;

	@OneToOne(cascade=CascadeType.REFRESH)
	private Child refresh;

	@OneToOne(cascade=CascadeType.ALL)
	private Child all;

        // getter and setter
}
 @Entity
public class Child {

	@Id @GeneratedValue
	private int id;
	private String name;
	
	public Child(String name) {
		this.name = name;
	}
	
	public Child() {}

	// getter and setter
}
  • 测试
public class Test_CascadeType {

	private static EntityManagerFactory fac;
	private EntityManager manager;
	
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		fac = Persistence.createEntityManagerFactory("test");
	}

	@Before
	public void setUp() throws Exception {
		manager = fac.createEntityManager();
	}
	
	@Test 
	public void persist() {
		Parent parent = new Parent();
		Child persist = new Child("persist");
		Child remove = new Child("remove");
		Child merge = new Child("merge");
		Child refresh = new Child("refresh");
		Child all = new Child("all");
		parent.setAll(all);
		parent.setMerge(merge);
		parent.setPersist(persist);
		parent.setRefresh(refresh);
		parent.setRemove(remove);
		/*
		// 这部分代码愿意是直接持久化parent对象,提交时会抛出RollbackException,但当提交第二个事务时则会抛出异常
		// org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
		// 据说解决方式是设置Parent的主键为非自增,暂时留在,请大牛们指教
		manager.getTransaction().begin();
		try {
			// 抛出异常,因为Child对象merge、remove、refresh的CascadeType未声明为persist类型,只能手动持久化
			manager.persist(parent);
			manager.getTransaction().commit();
			Assert.assertTrue(false);
		} catch (Exception e) {
			if(manager.getTransaction().isActive())
				manager.getTransaction().rollback();
			Assert.assertTrue(e instanceof RollbackException);
		}
		Assert.assertTrue(manager.contains(parent));
		*/
		manager.getTransaction().begin();
		// insert顺序是merge,refresh,remove,all,persist,parent,如果先持久化parent,则先insert parent,最后在update parent的外键值
		manager.persist(parent.getMerge());
		manager.persist(parent.getRefresh());
		manager.persist(parent.getRemove());
		manager.persist(parent);
		manager.getTransaction().commit();
		
		Query query = manager.createQuery("select o from Child o");
		List list = query.getResultList();
		Assert.assertEquals(5, list.size());
	}
	
	@Test
	public void merge() {
		Parent parent = manager.find(Parent.class, 1);
		Assert.assertEquals("persist", parent.getPersist().getName());// 其余同理
		
		// Clear the persistence context, causing all managed entities to become detached.
		// 将Entity能脱离EntityManager,避免长时间保持EntityManager打开占用资源并可以在不同的JVM之间传递Entity。
		manager.clear();
		parent.getMerge().setName("new merge");
		parent.getPersist().setName("new persist");
		// Merge the state of the given entity into the current persistence context.
		// return the instance that the state was merged to.
		Parent mp = manager.merge(parent);
		Assert.assertNotSame(mp, parent);
		
		Assert.assertEquals("new persist", parent.getPersist().getName());// 同refresh、remove
		Assert.assertEquals("persist", mp.getPersist().getName());
		
		Assert.assertEquals("new merge", parent.getMerge().getName());	// 同all
		Assert.assertEquals("new merge", mp.getMerge().getName());
		
		manager.getTransaction().begin();
		// manager.persist(parent); // 将抛出PersistenceObjectException:detached entity passed to persist
		manager.persist(mp);	//或者manager.merge(parent);必须commit才更新到数据库,此处persist等child对象已存在数据库中,故而无需再持久化
		manager.getTransaction().commit();
	}
	
	@Test
	public void refresh() {
		// 从数据库中获得实体
		Parent p1 = manager.find(Parent.class, 1);
		// 其他程序修改了数据库中的值
		modifyBYOther();
		// 缓存中的何真正要处理的值有所出入,是'脏'数据
		Assert.assertEquals("persist", p1.getPersist().getName());
		Assert.assertEquals("refresh", p1.getRefresh().getName());
		// 用refresh从数据库中获取最新的实体
		manager.refresh(p1);
		// 验证
		Assert.assertEquals("persist", p1.getPersist().getName());
		Assert.assertEquals("new", p1.getRefresh().getName());
	}
	
	@Test
	public void remove() {
		Parent parent = manager.find(Parent.class, 1);
		manager.getTransaction().begin();
		manager.remove(parent);
		manager.getTransaction().commit();
		
		Assert.assertNotNull(parent);
		Assert.assertNull(manager.find(Parent.class, 1));
		Query query = manager.createQuery("select o from Child o");
		List list = query.getResultList();
		Assert.assertEquals(3, list.size());
	}
	
	private void modifyBYOther() {
		manager.getTransaction().begin();
		Query query = manager.createQuery("update Child o set o.name = 'new'");
		query.executeUpdate();
		manager.getTransaction().commit();
	}
	

	@After
	public void tearDown() throws Exception {
		manager.close();
	}
	
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		fac.close();
	}

}
 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics