hibernate--持久对象的生命周期介绍
持久化对象的状态
:
1、 瞬时对象(Transient Object):使用new操作符初始化的对象不是立刻就持久的。它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回收
2、 持久化对象(Persistent Object):持久实例是任何具有数据库标识的实例,它有持久化管理器Session统一管理,持久实例是在事务中进行操作的----它们的状态在事务结束时同数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中。
3、 游离(离线)对象(Detached Object):Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,它们不再受hibernate管理。
Transient对象:随时可能被垃圾回收器回收(在数据库中没有于之对应的记录,应为是new初始化),而执行save()方法后,就变为Persistent对象(持久性对象),没有纳入session的管理
Persistent对象:在数据库有存在的对应的记录,纳入session管理。在清理缓存(脏数据检查)的时候,会和数据库同步。
Detached对象:也可能被垃圾回收器回收掉(数据库中存在对应的记录,只是没有任何对象引用它是指session引用),注引状态经过Persistent状态,没有纳入session的管理
1 package h.one.test; 2 3 import h.one.bean.User; 4 import h.one.utils.HibernateUtil; 5 6 import java.util.Date; 7 8 import org.hibernate.HibernateException; 9 import org.hibernate.Session; 10 import org.hibernate.Transaction; 11 import org.junit.Test; 12 13 public class testSave1 { 14 15 @Test 16 public void testSave1() { 17 Session session = null; 18 Transaction tx = null; 19 User user = null; 20 21 try { 22 session = HibernateUtil.getSession(); 23 tx = session.beginTransaction(); 24 25 // Transient状态 26 user = new User(); 27 user.setName("李四"); 28 user.setPassword("123"); 29 user.setCreateTime(new Date()); 30 user.setExpireTime(new Date()); 31 32 /* 33 * persistent状态 persistent状态的对象,当属性发生改变的时候,hibernate会自动和数据库同步 34 */ 35 session.save(user); 36 37 user.setName("王五"); 38 // 实际上user.setName("王五")此时已经发出一条update指令了。 39 // 也可以显示的调用update指定 40 // session.update(user); 41 42 tx.commit(); 43 } catch (Exception e) { 44 e.printStackTrace(); 45 tx.rollback(); 46 } finally { 47 HibernateUtil.closeSession(session); 48 } 49 50 /* 51 * 从此处开始session已经在上面关闭,这时user对象状态就变为detached状态, 52 * 所有user对象已经不被session管理,但数据库中确实存在与至对应的记录(王五)。 53 */ 54 // detached状态 55 user.setName("张三"); 56 57 try { 58 session = HibernateUtil.getSession(); 59 session.beginTransaction(); 60 /* 61 * 此时session又对user对象进行管理 当session发出update指定后,进行更新数据为(张三。) 62 */ 63 session.update(user); 64 65 // update后user对象状态又变为persistent状态 66 session.getTransaction().commit(); 67 /* 68 * 此时session提交事务,发出update语句 Hibernate: update User set name=?, 69 * password=?, createTime=?, expireTime=? where id=? 70 */ 71 } catch (HibernateException e) { 72 // TODO Auto-generated catch block 73 e.printStackTrace(); 74 session.getTransaction().rollback(); 75 } finally { 76 HibernateUtil.closeSession(session); 77 } 78 } 79 }
Hibernate加载数据:
两种:get()、load()
一、 Session.get(Class clazz, Serializable id)方法
* clazz:需要加载对象的类,例如:User.class
* id:查询条件(实现了序列化接口的对象):
例"4028802c46d255740146d25576320000"字符串已经实现了序列化接口。
返回值: 此方法返回类型为Object,也就是对象,然后我们再强行转换为需要加载的对象就可以了。
如果数据不存在,则返回null;
注:执行此方法时立即发出查询SQL语句。加载User对象
加载数据库中存在的数据,代码如下
1 @Test 2 public void testLoad() { 3 Session session = null; 4 Transaction tx = null; 5 6 try { 7 session = HibernateUtil.getSession(); 8 tx = session.beginTransaction(); 9 10 /* 11 * Object org.hibernate.Session.get(Class arg0, Serializable arg1) 12 * throws HibernateException arg0:需要加载对象的类,例如:User.class 13 * arg1:查询条件(实现了序列化接口的对象 14 * ):例"4028818a245fdd0301245fdd06380001"字符串已经实现了序列化接口。 15 * 此方法返回类型为Object,也就是对象,然后我们再强行转换为需要加载的对象就可以了。 如果数据不存在,则返回null 16 * 执行此方法时立即发出查询SQL语句。加载User对象。 17 */ 18 User user = (User) session.get(User.class,"4028802c46d255740146d25576320000"); 19 20 // 数据加载完后的状态为persistent状态。数据将与数据库同步。 21 System.out.println("user.name=" + user.getName()); 22 23 // 因为此的user为persistent状态,所以数据库进行同步为龙哥。 24 user.setName("龙哥"); 25 session.getTransaction().commit(); 26 } catch (HibernateException e) { 27 e.printStackTrace(); 28 session.getTransaction().rollback(); 29 } finally { 30 if (session != null) { 31 if (session.isOpen()) { 32 session.close(); 33 } 34 } 35 } 36 }
一、 Object Session.load(Class clazz, Serializable id) throws HibernateException
* clazz:需要加载对象的类,例如:User.class
* id:查询条件(实现了序列化接口的对象):例"4028802c46d255740146d25576320000"字符串已经实现了序列化接口。
* 此方法返回类型为Object,但返回的是代理对象。
* 执行此方法时不会立即发出查询SQL语句。只有在使用对象时,它才发出查询SQL语句,加载对象。
* 因为load方法实现了lazy(称为延迟加载、赖加载)
* 延迟加载:只有真正使用这个对象的时候,才加载(才发出SQL语句)
* hibernate延迟加载实现原理是代理方式。
* 采用load()方法加载数据,如果数据库中没有相应的记录,则会抛出异常对象不找到(org.hibernate.ObjectNotFoundException)
1 @Test 2 public void testLoad() { 3 Session session = null; 4 Transaction tx = null; 5 try { 6 session = HibernateUtil.getSession(); 7 tx = session.beginTransaction(); 8 9 User user = (User) session.load(User.class, 10 "4028802c46d255740146d25576320000"); 11 12 // 只有在使用对象时,它才发出查询SQL语句,加载对象。 13 System.out.println("user.name=" + user.getName()); 14 15 // 因为此的user为persistent状态,所以数据库进行同步为龙哥。 16 user.setName("发哥"); 17 18 session.getTransaction().commit(); 19 } catch (HibernateException e) { 20 e.printStackTrace(); 21 session.getTransaction().rollback(); 22 } finally { 23 if (session != null) { 24 if (session.isOpen()) { 25 session.close(); 26 } 27 } 28 } 29 }
Hbernate两种加载数据方式的区别:
get()方法默认不支持lazy(延迟加载)功能,而load支持延迟加载
get()方法在查询不到数据时,返回null,而load因为支持延迟加载,只有在使用对象时才加载,所以如果数据库中不在数据load会抛出异常(org.hibernate.ObjectNotFoundException)。
get()和load()只根据主键查询,不能根据其它字段查询,如果想根据非主键查询,可以使用HQL
hibernate更新数据:
建立使用hibernate进行更新数据时,先加载数据,然后再修改后更新。
否则一些字段可以会被null替换。
1 @Test 2 public void testDelete() { 3 Session session = null; 4 Transaction tx = null; 5 6 try { 7 session = HibernateUtil.getSession(); 8 tx = session.beginTransaction(); 9 10 User user = (User) session.load(User.class, 11 "4028802c46d255740146d25576320000"); 12 session.delete(user); 13 14 session.getTransaction().commit(); 15 } catch (HibernateException e) { 16 e.printStackTrace(); 17 session.getTransaction().rollback(); 18 } finally { 19 if (session != null) { 20 if (session.isOpen()) { 21 session.close(); 22 } 23 } 24 } 25 // transistent状态(数据库中没有配区的数据记录。) 26 }
query接口初步
Query session.createQuery(String hql)方法;
* hibernate的session.createQuery()方法是使用HQL(hibernate的查询语句)语句查询对象的。
* hql:是查询对象的,例如:"from User",其中from不区分大小写,而User是区分大小写,因为它是对象。是User类
* 返回Query对象。
* 执行这条语句后,Hibernate会根据配置文件中所配置的数据库适配器自动生成相应数据库的SQL语句。如:
ibernate: select user0_.id as id0_, user0_.name as name0_, user0_.password as password0_, user0_.createTime as createTime0_, user0_.expireTime as expireTime0_ from User user0_
1 @Test 2 public void testQuery1() { 3 Session session = null; 4 try { 5 session = HibernateUtil.getSession(); 6 session.beginTransaction(); 7 Query query = session.createQuery("from User"); 8 // 分页查询 9 query.setFirstResult(0);// 从哪一条记录开始查询,是从0开始计算 10 query.setMaxResults(2);// 分页每页显示多少条记录。 11 /* 12 * Query对象中有一个list()方式,将所有查询来的对象自动生成list对象返回。 13 */ 14 List userList = query.list(); 15 // 然后我们就可以显示数据了。 16 for (Iterator iter = userList.iterator(); iter.hasNext();) { 17 User user = (User) iter.next(); 18 System.out.print(user.getId() + " "); 19 System.out.println(user.getName()); 20 } 21 session.getTransaction().commit(); 22 } catch (HibernateException e) { 23 e.printStackTrace(); 24 session.getTransaction().rollback(); 25 } finally { 26 HibernateUtil.closeSession(session); 27 } 28 }
总结:
Hibernate是一个O/R映射框架(也称为ORM)
从ORM词来看,O---Object(对象模型);R--- Relational(关联模型),可以做对象和关联的一种映射,当然这只是部分功能,一个完善ORM框架应该具有更多的功能:如HQL相关的查询语句、提供缓存机制(一级缓存、二级缓存)。
Java开发数据库时,使用JDBC,但是需要编写大量相同的代码,这样不便提高生产效率,而hibernate可以让你不能编写大量的相同的代码。从而提高生产效率。另一方面,hibernate可以让我们更面对象化开发,还有一个移植性hibernate只需要更改配置文件(数据库适配器)的选项,就可以非常方便的移植到不同的数据库,而不需要重新编写不同数据库厂家所对应的JDBC、SQL语句了。还有hibernate可以解决阻抗不匹配(Java类中有继承关系,而关系型数据库中没有这个功能(目前数据库还不是面向对象,都是关系型数据库)),使用hibernate框架,侵入性比较好(因此hibernate称为轻量级框架)
O/R映射框架和使用环境:在程序中添加→修改→保存;查询可以批量,但是修改不可为批量性;程序中有大量的数据只读,这样就可以一次性读取到缓存中;对象间存在自然的关系;不需要数据库SQL特定的语句优化。
O/R映射框架不适合环境:聚集性操作:批量性添加、修改。批量的统计查询。
Configuration对象:读取hibernate配置文件(hibernate.cfg.xml或hiberante.properties)的. new Configuration()默认是读取hibernate.properties, 所以使用new Configuration().configure();来读取hibernate.cfg.xml配置文件
SessionFactory:是一个重量级对象,它的创建是耗时的。因为它对应一个数据库里所有配置,包括一些缓存机制都由SessionFactory来维护,它与二级缓存是绑定的。通常只创建一次,但它是线程安全的。
Session:是非线程安全的,它是通过SessionFactory来创建的。不要多个线程同时访问同一个Session,否则会出现一些未知问题。通常是一个请求对应一个Session,请求完成要关闭Session
Transaction:hibernate默认不是自动开启事务的,所以要手动开启事务、手动提交事务、手动回滚事务、手动关闭事务。当然可以通过配置文件配置成自动。一般使用手动。
Hibernate正常的开发思路:考虑对象模型这一块,把对象模型建立起来,把对象图建立起来,对象之间的关系建立起来、然后再编写映射文件(hbm),然后根据映射文件生成数据库表。数据库对我来说是透明的,我们只操作对象不用关心数据库。
——————————————————————————————————————————————————————————————————————————————
原文链接:http://www.cnblogs.com/sunhan/p/3808680.html