读书人

Hibernate3.2(4)生命周期示例、CRUD

发布时间: 2012-11-18 10:51:21 作者: rapoo

Hibernate3.2(四)生命周期示例、CRUD操作、Junit 3单元测试

?抽时间 总结junit3和junit4的相关测试方法 ,junit4采用的是annotations

junit3 命名规范: 测试类 xxxTest 测试方法void testxxx() ,方法中可以用断言assertEquals(expected, actual).

测试类需要继承TestCase , 在工程中新建一个source folder,在其中建好包,包名最好和要测的类所在的包一样。

?

1.用Junit 3 编写一个测试类SessionTest来测试 & 探索Hibernate 三种对象的生命周期

?

??熟悉hibernate的CRUD操作,主要方法有:get()、load()、save()、delete()、update()

package com.wyx.hibernate;import java.util.Date;import junit.framework.TestCase;import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.Transaction;import com.wyx.hibernate.utils.HibernateUtils;/** * 使用junit做测试多个方法比较方便,junit中还有setup()和Deardown(),用来初始化和销毁 * setup()一般放的是 * @author bird */public class SessionTest extends TestCase{//public 无returnpublic void testHello(){System.out.println("----------SessionTest.testHello()----------");//throw new  java.lang.RuntimeException();//this.assertEquals("hello", "no hello");}public void testSession(){Session session = HibernateUtils.getSession();Transaction ts = session.beginTransaction();User u = new User();try {//Transient状态//uid不需要赋值,自动赋值u.setName("李四");u.setPassword("123");u.setCreateTime(new Date());u.setExpireTime(new Date());session.save(u);//单步调试表明,在执行完save()后,uid的值才产生System.out.println("---------mark-----------");//save()后变成persistent状态u.setName("王五");//persistent状态的时候,不需要手动update,hibernate会自动和数据库同步//session.update(u);ts.commit();} catch (HibernateException e) {e.printStackTrace();ts.rollback();}finally{HibernateUtils.closeSession(session);}//Detached状态u.setName("张三");try {session = HibernateUtils.getSession();session.beginTransaction();session.update(u);session.getTransaction().commit();} catch (Exception e) {e.printStackTrace();ts.rollback();}finally{HibernateUtils.closeSession(session);}}} 

?

?

?运行结果:

----------SessionTest.testHello()----------
---------mark-----------
Hibernate: insert into User (name, password, createTime, expireTime, id) values (?, ?, ?, ?, ?)
Hibernate: update User set name=?, password=?, createTime=?, expireTime=? where id=?
Hibernate: update User set name=?, password=?, createTime=?, expireTime=? where id=?

?运行结果表明,一个对象处于Persistent状态时,当属性发生改变的时候,Hibernate会自动和数据库同步,Hibernate只是把这些数据放在缓存中处理,而且是在commit()提交的时候才执行所有的数据库操作。

产生多条sql语句的原因是:hibernate在修改数据之前要先照一个快照,接下来修改了对象u.setName("王五"),在commit的时候,需要清理缓存(内从中的对象),脏数据是指没有提交的数据,commit()之前清理缓存的这个过程中要执行脏数据对比,脏数据对比的主要工作是处理哪些数据要发成insert,哪些数据要发成update语句。

当session关闭的时候,session已经不再管理u对象,u对象虽然变成了Detached状态,但是数据库中该条记录依然存在,当执行update的时候,数据库中u对应的那条记录name字段又变成了“张三”,update之后,该u对象又变成了Persistent状态的。

?

?接着在SessionTest中写一个方法,运行:

public void testReadByGetMethod(){Session session = HibernateUtils.getSession();try {session.beginTransaction();//将数据库中对应id的那条记录取出来存在User对象中,此时立即产生sql语句User u =(User)session.get(User.class, "402881fa2edaffe9012edaffea5c0001");System.out.println("-------------mark----------------");//修改u , persistent状态的时候,不需要手动update,hibernate会自动和数据库同步u.setName("jeff");session.getTransaction().commit();} catch (HibernateException e) {session.getTransaction().rollback();e.printStackTrace();}finally{HibernateUtils.closeSession(session);}}

?

?运行结果:

Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.password as password0_0_, user0_.createTime as createTime0_0_, user0_.expireTime as expireTime0_0_ from User user0_ where user0_.id=?
-------------mark----------------
Hibernate: update User set name=?, password=?, createTime=?, expireTime=? where id=?

?

?

public void testReadByGetMethod1(){Session session = HibernateUtils.getSession();try {session.beginTransaction();User u =(User)session.get(User.class, "adfsafa");session.getTransaction().commit();} catch (HibernateException e) {session.getTransaction().rollback();e.printStackTrace();}finally{HibernateUtils.closeSession(session);}}

?运行结果:Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.password as password0_0_, user0_.createTime as createTime0_0_, user0_.expireTime as expireTime0_0_ from User user0_ where user0_.id=?
调试跟踪表明,u对象值为null,但是单元测试没有报错,所以采用get()加载数据,如果数据中不存在相应的数据,返回null。

?

public void testReadByLoadMethod1(){Session session = HibernateUtils.getSession();try {session.beginTransaction();//不会发出查询sql,因为load方法实现了lazy()//懒加载 or 延迟加载,真正使用这个对象的时候,才加载(发出sql语句)//hibernate延迟加载实现原理是代理方式User u =(User)session.load(User.class, "402881e62ed3df84012ed3df85510001");System.out.println("----------mark------------");System.out.println("u.name: " + u.getName());session.getTransaction().commit();} catch (HibernateException e) {session.getTransaction().rollback();e.printStackTrace();}finally{HibernateUtils.closeSession(session);}}

?

?

运行结果:

----------mark------------
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.password as password0_0_, user0_.createTime as createTime0_0_, user0_.expireTime as expireTime0_0_ from User user0_ where user0_.id=?
u.name: jeff

代理类是使用CGLIB工具生成代理类,代理类继承了User。

public void testReadByLoadMethod2(){Session session = HibernateUtils.getSession();try {session.beginTransaction();//采用load加载数据,如果数据库中没有相应数据,//那么抛出ObjectNotFoundException的异常User u =(User)session.load(User.class, "adadfafdf");System.out.println("----------mark------------");System.out.println("u.name: " + u.getName());session.getTransaction().commit();} catch (HibernateException e) {session.getTransaction().rollback();e.printStackTrace();}finally{HibernateUtils.closeSession(session);}}

?运行结果:

----------mark------------
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.password as password0_0_, user0_.createTime as createTime0_0_, user0_.expireTime as expireTime0_0_ from User user0_ where user0_.id=?
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.wyx.hibernate.User#adadfafdf]

从上述get和load的测试方法可见:

1. get()不支持lazy, load()是支持lazy的(懒加载);

2. get()查询数据的时候,查不到返回null。而load()抛出org.hibernate.ObjectNotFoundException。注意,执行load方法的时候是不会报错的,在调用保存load的那个对象时才会抛出异常。

?

测试update():

public void testUpdate1(){Session session = HibernateUtils.getSession();try {session.beginTransaction();//虽然是我们自己new出来的,但是id在数据库中存在,所以这属于手动构造的 Detached 对象User u = new User();u.setId("402881e62ed40ec1012ed40ec2f10001");u.setName("小明");u.setPassword("123");session.update(u);session.getTransaction().commit();} catch (HibernateException e) {session.getTransaction().rollback();e.printStackTrace();}finally{HibernateUtils.closeSession(session);}}

?测试结果:

Hibernate: update User set name=?, password=?, createTime=?, expireTime=? where id=?

虽然手动构造的Detached对象可以update到数据库,但是,万一有字段没setvalue就会更新空数据进DB,所以最好的做法还是操作一个从数据库get或load的对象,因为该对象已经填充了值。

?

测试Delete():

public void testDelete(){Session session = HibernateUtils.getSession();try {session.beginTransaction();User u = (User)session.load(User.class, "402881e62ed40ec1012ed40ec2f10001");session.delete(u);session.getTransaction().commit();} catch (HibernateException e) {session.getTransaction().rollback();e.printStackTrace();}finally{HibernateUtils.closeSession(session);}}

?测试结果:

Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.password as password0_0_, user0_.createTime as createTime0_0_, user0_.expireTime as expireTime0_0_ from User user0_ where user0_.id=?
Hibernate: delete from User where id=?

在删除一条记录的时候,操作的也是对象,所以把对象根据id用get或load获取到,然后session.delete(u);

?

小结:

transient状态的特征:

1. 在数据库中没有与之匹配的记录;

2. 没有纳入session的管理;

Persistent状态的特征:

1. 对象在数据库中有与之匹配的记录;

2. 纳入了session的管理;

3. 在清理缓存(脏数据检查)的时候,会和数据库同步(内存检查、清理缓存的目的是:看缓存发生有没有变化,从而判断到底发什么hql语句,eg:在save完了后,修改了对象,发了两条:一条insert一条update,这就是脏数据检查的好处);

Detached状态的特征:

1. 在数据库中有与之匹配的记录;

2. 没有纳入session的管理;

?

?

在实际应用中,我们经常需要根据表中的非id字段查询一个对象(一条记录),或者全部的数据,就要用到HQL。

读书人网 >软件架构设计

热点推荐