上面的这个图是Hiberante应用程序的结构,
对上图中各项的说明如下:(1)Application:应用 (2)Persistent Object:持久化对象(3)hibernate.properties:Hibernate属性文件/Hibernate配置文件 (4)XML Mapping:Hibernate映射文件 (5)Database:数据库
由上图可以看出,Hibernate是通过一系列的配置文件和数据库来实现持久化对象的持久化操作的。
为了使用Hibernate,需要创建与数据库中的表对应的持久化对象,然后再通过影射文件将持久化对象中的属性与数据库表中的字段对应起来。这样才能通过持久化对象完成对数据库表中的数据的增加、修改、查询和删除操作。
Hibernate主要包括三个组件:
(1)连接管理组件:它提供了高效的数据库连接管理。数据库连接是和数据库进行交互的唯一渠道,建立和关闭一个连接需要耗费大量的资源。所以现在的应用程序都采用连接池的方法来管理与数据库的连接,避免频繁的建立和关闭数据库连接
(2)事务管理组件:通过事务,一次可以执行多个SQL语句,而且能够保证这些语句执行成功或者都不成功
(3)对象/关系映射组建:对象/映射技术可以实现从对象模型到数据库中关系模型的映射工作。通过这一技术,Hibernate实现了对象的持久化操作。
Hinernate的体系结构(运行时)
由于Hibernate非常灵活,而且提供了多种运行时的结构组成方案,这里介绍的时一个“最全面”的体系结构,它最大程度的完成了对持久层功能的封装,也就使得在开发中要完成的工作量最少,是在开发中最经常使用的一种方式。这种方式把JDBC/JTA都交由Hibernate去完成,而不需要对这一部分进行任何处。
各个部分的主要功能如下
SessionFactory:它保存了对当前数据库配置的所有映射关系,它是将某个数据库的映射关系经过编译之后全部保存在内存中的。 它还是生成Session的工厂,它在进行实例化的过程中将会用到ConnectionProvider。一个SessionFactory对应一个数据库连接,当数据库连接改变时需要修改SessionFactory
Sesion:是进行持久化操作的基础,所有的持久化操作都是在Session的基础上进行的。它相当与JDBC中的Connection。它是Hibernate的持久化管理器的核心,提供了一系列的持久化操作方法。另外,它还持有一个针对持久化对象的一级缓存,在遍历持久化对象或者根据持久化标识查找对象的时候会用到。
Transation:功能上和数据库中的事务完全一样,通过它实现对数据库中事务的控制。Transation对象是Session对象产生的,所以他的生命周期比Session短。一个Session的生命周期中可以有多个Transaction对象。
ConnectonProvider:主要作用是生成与数据库建立了连接的JDBC对象,同时他还作为数据库连接的缓冲池。通过ConnectionProvider实现了应用程序和底层的DataSource和DriverManager的隔离。
TransactionFactory:是生成Transaction对象的工厂,通过TransactionFactory实现了事务的封装,使其具体的实现方法与应用程序无关。
Hibernate对象的生命周期
一共有三种生命周期:
(1)瞬态:表示该实体对象在内存中是自由存在的,也就是说与数据库中的数据没有任何的关联。即,该实体从未与任何持久化上下文联系过,没有持久化标识(相当与主键)。瞬态实体的特征有:
与数据库中的记录没有任何关联,也就是没有与其相关联的数据库记录
与Session没有任何关系,也就是没有通过Session对象的实例对其进行任何持久化的操作。
(2)持久态:指该实体对象处于Hibernate框架所管理的状态,也就是说这个实体对象是与Session对象的实例相关的。处于持久态的实体对象的最大特征是对其所作的任何变更操作都将被Hibernate持久化到数据库中。处于持久态的对象具有的特征为:
每个持久态对象都于一个Session对象关联
处于持久态的对象是于数据库中的记录相关联的
Hibernate会根据持久态对象的属性的变化而改变数据库中的相应记录
(3)游离态:处于持久态的实体对象,当他不再与Session对象关联时,这个对象就变成了游离态。。游离态对象的特征有:
游离态对象一定是由持久态对象转换而来
游离态实体不再于Session关联
游离态实体对象与数据库中的数据没有直接联系,主要表现在对其进行的修改不再影响到数据库中的数据
游离态实体对象在数据库中有相应的数据记录(如果该记录没有被删除)
判断一个实体对象是否处于瞬态:
该实体对象的<id>属性(如果存在)的值为空
如果在映射文件中为<id>设置了unsaved-value属性,并且实体对象的id属性的值与unsaved-value属性的值相同
如果这个实体对象配置version属性,并且version属性的值为空
在映射文件中为version属性设置了unsaved-value属性,并且version属性的值与unsaved-value属性的值相同。
如果设置了interceptor,并且interceptor的isUnsaved()方法的返回值为true
满足上述条件的实体对象就处于瞬态,否则为游离态(前提是不处于持久态)
下面通过一段代码来说明状态问题:
public class LifeCycle
{ public static final SessionFactory sessionFactory;
static { sessionFactory = new Configuration().configure().buildSessionFactory(); } public static void main(String[] args) { LifeCycle.lifecycle(); } public static void lifecycle() { // 创建游离态实体对象User User user = new User(); user.setName( "abc" + String.valueOf( Math.random() ) ); // 为了避免两次运行的用户名重复,所以增加了随机数 user.setPassword( "def" ); // user仍然处于游离态 Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction(); // 此时user对象仍然是Transient状态 session.save( user ); // 此时,user对象已经被纳入了Hibernate的实体管理容器中,并转变为Persistent状态 System.out.println( "User 1:" + user ); // 此时的id已经有值了。 get( user.getId() ); // 但并未真正的执行数据库的操作,所以无法得到对象的值 tx.commit(); // 事务被提交后,将向数据库的用户表中插入一条记录 System.out.println( "Transaction 1 commit!" ); get( user.getId() ); // 这时可以由数据库中得到刚才插入的user对象了。 Transaction tx2 = session.beginTransaction(); user.setPassword( "mmmmmmmmmmmmm" ); tx2.commit(); // 虽然这个事务中并没有调用Session的save()方法来保存user对象 // 但由于user对象处于Persistent状态,所以对user对象所做的任何修改都将被持久化到数据库中 // 那么数据库中的用户密码也应该变为了def。 System.out.println( "Transaction 2 commit!" ); session.close(); get( user.getId() );
// 此时密码已经变为新的值了 } public static User get( String id ) { Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); User user = (User)session.get( User.class, id ); // Hibernate在返回User对象之间会将其纳入到Hibernate的实体管理容器中 // 所以,这时的user对象是Persistent状态的 display( user ); tx.commit(); session.close(); return user; } public static void display( Object obj ) { System.out.println( obj ); } } 提示1:Hibernate支持四种数据库连接池的组件
(1)C3P0。这是Hiberante自身提供的。其文档地址见:www./projects/c3p0/index.html;有关Hibernte中配置c3p0的文档参考:www./214.html
(2)DBCP:它是Apache软件基金组织的一个开源项目。由于在Hibernte3中不再提供DBCConnectionProvider类来直接使用DBCP建立数据库的连接池,在这里提供两种方法解决这个问题。一种是仿照Hibernate2中的DBCPConnectionProvider类自己实现一个使用DBCP并实现了ConnetcitonProvider接口的连接池类。另一种是让应用服务器通过JNDI的方式来提供数据库的连接,Hibernate通过JNDI得到数据库的连接。DBCP的详细信息见:http://jakarta./commons/dbcp/。关于自己实现ConnectionProvider接口的方法见http://wiki./jakarta-commons/DBCP/Hibernate
(3)Proxool:也是开放源代码的提供数据库连接池的组件。其官方网站为:http://proxool.。有关配置的详细参数见官方网站
|
|
来自: 元傲一 > 《持久化层技术学习》