【Hibernate3】(2)持久化

一. 單例工廠類

因爲我們每一個測試方法都需要讀取配置文件,創建工程,創建session,所以我們可以寫這樣子的一個工具類來做這些操作:
public class HibernateUtil {

	private static Configuration cfg = null;
	private static SessionFactory factory = null;

	static {
		if (cfg == null) {
			cfg = new Configuration().configure();
		}
		if (factory == null) {
			factory = cfg.buildSessionFactory();
		}
	}

	public static SessionFactory getSessionFactory() {
		return factory;
	}

	public static Session getSession() {
		return factory.openSession();
	}

	public static void closeSession(Session session) {
		if (session != null) {
			session.close();
		}
	}
<span style="font-family:Microsoft YaHei;">}</span>
這樣就大大簡化了我們的代碼。

二. 持久化對象的三種狀態

1. 瞬時對象

使用new操作符初始化的對象不是立刻就持久的,是瞬時的。

2. 持久化對象

在使用sql的insert、update、delete語句吧內存中的對象同步到數據庫中,即當持久對象修改數據的時候,會自動同步到數據庫中。

3. 離線狀態

在session關閉之後就處於離線狀態,不能同步數據到數據庫中了,可以使用sql的insert、update、delete語句重新實現持久化,同步數據。

三. Session的常用方法

1. save和saveOrUpdate的區別

我們這樣子修改添加的方法:
	public void testAdd() {
		User user = new User();
		user.setUsername("張三");
		user.setSex("男");
		user.setAge(27);
		user.setBirthday(new Date());
		user.setSalary(100.5);
		user.setId(2);

		Session session = HibernateUtil.getSession();
		// 創建及開啓事務對象
		Transaction trans = null;
		try {
			trans = session.beginTransaction();
			// 添加User實體對象
			session.save(user);
			trans.commit();
		} catch (HibernateException e) {
			trans.rollback();
			e.printStackTrace();
		} finally {
			HibernateUtil.closeSession(session);
		}
	}
給User指定了id,但是發現查看數據庫,還是遞增的向後排,並沒有理我們的設定的id爲2,相當於執行了save方法。
將save改成saveOrUpdate方法,執行發現將id爲2的內容修改成了我們設置的User,相當於執行了update方法;如果setId傳了一個數據庫不存在的值,那麼它執行的又變回了save方法。
還有一點需要注意的是不論是save方法還是saveOrUpdate方法對持久對象不起作用。
	/**
	 * save和saveOrUpdate方法對持久對象都不起作用
	 */
	public void testAdd2() {

		Session session = HibernateUtil.getSession();
		// 創建及開啓事務對象
		Transaction trans = null;
		try {
			trans = session.beginTransaction();
			// 添加User實體對象
			User user = (User) session.get(User.class, 2);
			session.save(user);
			// session.saveOrUpdate(user);
			trans.commit();
		} catch (HibernateException e) {
			trans.rollback();
			e.printStackTrace();
		} finally {
			HibernateUtil.closeSession(session);
		}
	}
執行發現,並沒有添加新的數據出來,當修改user的數據時,是持久對象發生了同步update方法,並不是save或者saveOrUpdate起了作用。

2. persist和save以及merge和update的區別

persist和save都可以把對象存進數據庫,沒有什麼區別。
接下來我們看這個方法:
	public void testUpdate() {
		User user = new User();
		user.setUsername("陳小春");
		user.setSex("男");
		user.setAge(40);
		user.setBirthday(new Date());
		user.setSalary(110.5);
		user.setId(3);

		Session session = HibernateUtil.getSession();
		// 創建及開啓事務對象
		Transaction trans = null;
		try {
			trans = session.beginTransaction();
			User u = (User) session.get(User.class, 3);
			session.update(user);
			trans.commit();
		} catch (HibernateException e) {
			trans.rollback();
			e.printStackTrace();
		} finally {
			HibernateUtil.closeSession(session);
		}
	}
執行後會發現報錯了,說有兩個相同id的實體,這裏修改成merge而不是update的時就會正常執行。實際上執行merge方法時,會先將merge參數中user的全部屬性賦值給u對象,然後更新u對象。

3. lock(已淘汰)和update方法的區別

lock是原來爲了將對象重新持久化而使用的一個方法,現在已經廢棄了,使用update代替了。

4. save、update、get、delete方法的執行順序和flush方法

在一個session的執行過程中,不管save、update、get和delete寫在程序的哪裏,他們的執行順序都是先get,然後save,然後update最後delete,如果想要先執行某個方法,那麼需要在這個方法之後調用flush方法即可:
	public void testOrder() {
		User user = new User();
		user.setUsername("第一個");
		user.setSex("男");
		user.setAge(27);
		user.setBirthday(new Date());
		user.setSalary(100.5);
		user.setId(2);

		Session session = HibernateUtil.getSession();
		// 創建及開啓事務對象
		Transaction trans = null;
		try {
			trans = session.beginTransaction();

			User u = (User) session.get(User.class, 10);
			u.setUsername("更新的第10條");

			session.delete(session.get(User.class, 7));
			session.delete(session.get(User.class, 8));
			
			session.flush();

			// 添加User實體對象
			session.save(user);

			user = new User();
			user.setUsername("新的一個");
			user.setAge(17);
			user.setBirthday(new Date());
			user.setSalary(294.4);
			user.setSex("女");
			session.save(user);

			trans.commit();
		} catch (HibernateException e) {
			trans.rollback();
			e.printStackTrace();
		} finally {
			HibernateUtil.closeSession(session);
		}
	}

5. clear及evict方法

	public void testclear() {

		Session session = HibernateUtil.getSession();
		// 創建及開啓事務對象
		Transaction trans = null;
		try {
			trans = session.beginTransaction();
			Query query = session
					.createQuery("from com.thr.hibernate.entity.User");
			List<User> users = query.list();
			// session.clear();
			for (User user : users) {
				user.setUsername(user.getUsername() + "new");
			}

			trans.commit();
		} catch (HibernateException e) {
			trans.rollback();
			e.printStackTrace();
		} finally {
			HibernateUtil.closeSession(session);
		}
	}
當執行了query.list方法後,查詢出來的集合已經放在了緩存中,可以持久化更新,但是如果執行了session.clear()方法後,那麼緩存就都清空了,後面的users並不持久化,無法更新了。
修改代碼:
			int i = 0;
			for (User user : users) {
				i++;
				if (i == 3) {
					session.evict(user);
				}
				user.setUsername(user.getUsername() + "new");
			}
意思是當執行到第3個元素的時候,將其從緩存中剔除掉,那麼第3個元素就不會執行更新語句了。

6. get和load方法的區別

	public void test() {

		Session session = HibernateUtil.getSession();
		// 創建及開啓事務對象
		Transaction trans = null;
		try {
			trans = session.beginTransaction();

			//User user = (User) session.get(User.class, 10);
			User user = (User) session.load(User.class, 10);
			System.out.println(user.getUsername());

			trans.commit();
		} catch (HibernateException e) {
			trans.rollback();
			e.printStackTrace();
		} finally {
			HibernateUtil.closeSession(session);
		}
	}
使用get方法的時候在執行get方法後,立刻就進行了查詢操作;但使用load方法會延時加載,在需要使用到user的時候纔會執行查詢的操作。是否開啓懶加載還可以在hibernate的配置文件中通過配置lazy="false"來設置:
<span style="white-space:pre">	</span><class name="com.thr.hibernate.entity.User" table="T_USER" lazy="true">
當查詢不到結果的時候get方法會返回null,而load方法會報異常。

7. list和iterator方法

	public void testIterator() {
		Session session = HibernateUtil.getSession();
		// 創建及開啓事務對象
		Transaction trans = null;
		try {
			trans = session.beginTransaction();
			Query query = session
					.createQuery("from com.thr.hibernate.entity.User");
			// List<User> users = query.list();
			// for (User user : users) {
			// System.out.println(user);
			// }
			Iterator<User> it = query.iterate();
			while (it.hasNext()) {
				System.out.println(it.next());
			}
			it = query.iterate();
			while (it.hasNext()) {
				System.out.println(it.next());
			}

			trans.commit();
		} catch (HibernateException e) {
			trans.rollback();
			e.printStackTrace();
		} finally {
			HibernateUtil.closeSession(session);
		}
	}
使用註釋中的list方法是執行了一條查詢,直接查出了所有的數據,如果第二次執行list還是會查詢所有的數據;而使用iterator第一次查詢是查出了所有的id,然後使用id去查詢每一條數據,如果有第二次的話,還是去查詢所有的id,如果發現和第一次id有一樣的,會直接使用第一次的數據,沒有多餘的操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章