【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有一样的,会直接使用第一次的数据,没有多余的操作。

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