JPA实体状态&联级操作
JPA的实体具有四种状态,如图所示:

?
public class Test_CascadeType {private static EntityManagerFactory fac;private EntityManager manager;@BeforeClasspublic static void setUpBeforeClass() throws Exception {fac = Persistence.createEntityManagerFactory("test");}@Beforepublic 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());}@Testpublic 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、removeAssert.assertEquals("persist", mp.getPersist().getName());Assert.assertEquals("new merge", parent.getMerge().getName());// 同allAssert.assertEquals("new merge", mp.getMerge().getName());manager.getTransaction().begin();// manager.persist(parent); // 将抛出PersistenceObjectException:detached entity passed to persistmanager.persist(mp);//或者manager.merge(parent);必须commit才更新到数据库,此处persist等child对象已存在数据库中,故而无需再持久化manager.getTransaction().commit();}@Testpublic 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());}@Testpublic 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();}@Afterpublic void tearDown() throws Exception {manager.close();}@AfterClasspublic static void tearDownAfterClass() throws Exception {fac.close();}}??