一、简介
Hibernate 架构是分层的,作为数据访问层,你不必知道底层 API 。Hibernate 利用数据库以及配置数据来为应用程序提供持续性服务(以及持续性对象)。
下面是一个非常高水平的 Hibernate 应用程序架构视图。
下面是一个详细的 Hibernate 应用程序体系结构视图以及一些重要的类。
Hibernate 使用不同的现存 Java API,比如 JDBC,Java 事务 API(JTA),以及 Java 命名和目录界面(JNDI)。JDBC 提供了一个基本的抽象级别的通用关系数据库的功能, Hibernate 支持几乎所有带有 JDBC 驱动的数据库。JNDI 和 JTA 允许 Hibernate 与 J2EE 应用程序服务器相集成。
下面的部分简要地描述了在 Hibernate 应用程序架构所涉及的每一个类对象。
配置对象
配置对象是你在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造。它代表了 Hibernate 所需一个配置或属性文件。配置对象提供了两种基础组件。
- 数据库连接:由 Hibernate 支持的一个或多个配置文件处理。这些文件是 hibernate.properties 和 hibernate.cfg.xml。
- 类映射设置:这个组件创造了 Java 类和数据库表格之间的联系。
SessionFactory 对象
配置对象被用于创造一个 SessionFactory 对象,使用提供的配置文件为应用程序依次配置 Hibernate,并允许实例化一个会话对象。SessionFactory 是一个线程安全对象并由应用程序所有的线程所使用。
SessionFactory 是一个重量级对象所以通常它都是在应用程序启动时创造然后留存为以后使用。每个数据库需要一个 SessionFactory 对象使用一个单独的配置文件。所以如果你使用多种数据库那么你要创造多种 SessionFactory 对象。
Session 对象
一个会话被用于与数据库的物理连接。Session 对象是轻量级的,并被设计为每次实例化都需要与数据库的交互。持久对象通过 Session 对象保存和检索。
Session 对象不应该长时间保持开启状态因为它们通常情况下并非线程安全,并且它们应该按照所需创造和销毁。
Transaction 对象
一个事务代表了与数据库工作的一个单元并且大部分 RDBMS 支持事务功能。在 Hibernate 中事务由底层事务管理器和事务(来自 JDBC 或者 JTA)处理。
这是一个选择性对象,Hibernate 应用程序可能不选择使用这个接口,而是在自己应用程序代码中管理事务。
Query 对象
Query 对象使用 SQL 或者 Hibernate 查询语言(HQL)字符串在数据库中来检索数据并创造对象。一个查询的实例被用于连结查询参数,限制由查询返回的结果数量,并最终执行查询。
Criteria 对象
Criteria 对象被用于创造和执行面向规则查询的对象来检索对象。
执行原理与流程
a、应用程序先调用Configuration类,该类读取Hibernate配置文件及映射文件中的信息,
b、并用这些信息生成一个SessionFactory对象,
c、然后从SessionFactory对象生成一个Session对象,
d、并用Session对象生成Transaction对象;
e、可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()、createQuery()等方法对进行CURD等操作;
f、提交事物。
二、配置
1、所需jar包
2、Hibernate.cfg.xml
<!--标准的XML文件的起始行,version='1.0'表明XML的版本,encoding='gb2312'表明XML文件的编码方式-->
<?xml version='1.0' encoding='gb2312'?>
<!--表明解析本XML文件的DTD文档位置,DTD是Document Type Definition 的缩写,即文档类型的定义,XML解析器使用DTD文档来检查XML文件的合法性。
hibernate.sourceforge.net/hibernate-configuration-3.0dtd可以在Hibernate3.1.3软件包中的src\org\hibernate目录中找到此文件-->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!--声明Hibernate配置文件的开始-->
<hibernate-configuration>
<!--表明以下的配置是针对session-factory配置的,SessionFactory是Hibernate中的一个类,
这个类主要负责保存HIbernate的配置信息,以及对Session的操作-->
<session-factory>
<!--配置数据库的驱动程序,Hibernate在连接数据库时,需要用到数据库的驱动程序-->
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver </property>
<!--设置数据库的连接url:jdbc:oracle:thin:@localhost:1521:orcl,其中localhost表示oracle数据库服务器名称,此处为本机,orcl是数据库名-->
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:orcl</hibernate>
<!--连接数据库是用户名-->
<property name="hibernate.connection.username">scott</property>
<!--连接数据库是密码-->
<property name="hibernate.connection.password">123456 </property>
<!--数据库连接池的大小-->
<property name="hibernate.connection.pool.size">20 </property>
<!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于查错,程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。
项目部署后可以设置为false,提高运行效率-->
<property name="hibernate.show_sql">true </property>
<!--jdbc.fetch_size是指Hibernate每次从数据库中取出并放到JDBC的Statement中的记录条数。Fetch Size设的越大,读数据库的次数越少,速度越快,
Fetch Size越小,读数据库的次数越多,速度越慢-->
<property name="jdbc.fetch_size">50 </property>
<!--jdbc.batch_size是指Hibernate批量插入,删除和更新时每次操作的记录数。Batch Size越大,
批量操作的向数据库发送Sql的次数越少,速度就越快,同样耗用内存就越大-->
<property name="jdbc.batch_size">23 </property>
<!--jdbc.use_scrollable_resultset是否允许Hibernate用JDBC的可滚动的结果集。对分页的结果集。对分页时的设置非常有帮助-->
<property name="jdbc.use_scrollable_resultset">false </property>
<!--connection.useUnicode 连接数据库时是否使用Unicode编码-->
<property name="Connection.useUnicode">true </property>
<!--connection.characterEncoding连接数据库时数据的传输字符集编码方式,最好设置为gbk,用gb2312有的字符不全-->
<property name="connection.characterEncoding">gbk </property>
<!--hibernate.dialect 是Hibernate使用的数据库方言,就是要用Hibernate连接那种类型的数据库服务器。-->
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<!--指定映射文件为“hibernate/ch1/UserInfo.hbm.xml”-->
<mapping resource="org/mxg/UserInfo.hbm.xml">
</session-factory>
</hibernate-configuration>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- 连接驱动 -->
<property name="driverClassName" value="${jdbc.driverClassName}" />
<!-- 连接url -->
<property name="url" value="${jdbc.url}" />
<!-- 连接用户名 -->
<property name="username" value="${jdbc.username}" />
<!-- 连接密码 -->
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="hbSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<!-- hibernate配置文件位置 -->
<value>WEB-INF/hibernate.cfg.xml </value>
</property>
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
<property name="hibernateProperties">
<props>
<!--针对oracle数据库的方言,特定的关系数据库生成优化的SQL -->
<prop key="hibernate.dialect"> org.hibernate.dialect.OracleDialect </prop>
<!--选择HQL解析器的实现 -->
<prop key="hibernate.query.factory_class"> org.hibernate.hql.ast.ASTQueryTranslatorFactory </prop>
<!-- 是否在控制台打印sql语句 -->
<prop key="hibernate.show_sql">true </prop>
<!-- 在Hibernate系统参数中hibernate.use_outer_join被打开的情况下,该参数用来允许使用outer join来载入此集合的数据。 -->
<prop key="hibernate.use_outer_join">true </prop>
<!-- 默认打开,启用cglib反射优化。cglib是用来在Hibernate中动态生成PO字节码的,打开优化可以加快字节码构造的速度 -->
<prop key="hibernate.cglib.use_reflection_optimizer">true </prop>
<!-- 输出格式化后的sql,更方便查看 -->
<prop key="hibernate.format_sql">true </prop>
<!-- “useUnicode”和“characterEncoding”决定了它是否在客户端和服务器端传输过程中进行Encode,以及如何进行Encode -->
<prop key="hibernate.connection.useUnicode">true </prop>
<!-- 允许查询缓存, 个别查询仍然需要被设置为可缓存的. -->
<prop key="hibernate.cache.use_query_cache">false </prop>
<prop key="hibernate.default_batch_fetch_size">16 </prop>
<!--连接池的最大活动个数 -->
<prop key="hibernate.dbcp.maxActive">100 </prop>
<!-- 当连接池中的连接已经被耗尽的时候,DBCP将怎样处理(0 = 失败,1 = 等待,2 = 增长) -->
<prop key="hibernate.dbcp.whenExhaustedAction">1 </prop>
<!-- 最大等待时间 -->
<prop key="hibernate.dbcp.maxWait">1200 </prop>
<!-- 没有人用连接的时候,最大闲置的连接个数 -- >
<prop key="hibernate.dbcp.maxIdle">10 </prop>
<!-- 以下是对prepared statement的处理,同上。 -->
<prop key="hibernate.dbcp.ps.maxActive">100 </prop>
<prop key="hibernate.dbcp.ps.whenExhaustedAction">1 </prop>
<prop key="hibernate.dbcp.ps.maxWait">1200 </prop>
<prop key="hibernate.dbcp.ps.maxIdle">10 </prop>
</props>
</property>
</bean>
3、hibernate.properties 数据库的配置信息
##---------Oracle---------
#hibernate.databaseType=oracle
#hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
#jdbc_url=jdbc:oracle:thin:@192.168.10.82:1521:ora11g
#jdbc_username=valleyplatform_test
#jdbc_password=valleyplatform_test
#jdbc_testsql=select * from dual
##---------MySQL---------
hibernate.databaseType=mysql
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
jdbc_url=jdbc:mysql://192.168.1.204:3306/platform-appraise
jdbc_username=root
jdbc_password=123456
jdbc_testsql=select X
##SQLServer
#hibernate.databaseType=mssql
#hibernate.dialect=org.hibernate.dialect.SQLServer2008Dialect
#jdbc_url=jdbc:jtds:sqlserver://192.168.10.181:1433/platform2-branches-gxr
#jdbc_username=sa
#jdbc_password=
#jdbc_testsql=select 1
##---------DM达梦---------
#hibernate.databaseType=oracle
#hibernate.dialect=org.hibernate.dialect.DmDialect
#jdbc_url=jdbc:dm://192.168.10.166:5236/DAMENG
#jdbc_username=PLATFORM2-BRANCHES-GXR
#jdbc_password=PLATFORM2-BRANCHES-GXR
#jdbc_password=sginfo123
#jdbc_testsql=select id from dual
##---------H2---------
##Database config
#表生成策略
hibernate.hbm2ddl.auto=update
#是否打印SQL语句
hibernate.show_sql=false
#在 log 和 console 中打印出更漂亮的 SQL。
hibernate.format_sql=false
如果开启,Hibernate 将在 SQL 中生成有助于调试的注释信息,默认值为 false。
hibernate.use_sql_comments=false
hibernate.hbm2ddl.auto的四个属性解释 这个属性标签中有四个参数可以写,这四个参数是对数据库中插入的进行不同的操作,分别为:
(1)create-drop
(2)create
(3)update
(4)validate
下面分别来介绍他们的作用以及对数据库中的影响
(1) create-drop create-drop:表示在hebarinate初始化时创建表格,程序运行结束的时候会删除相应的表格,在实际项目中不用
(2)create 在hibernate初始化时会创建表格,在运行结束之后不删除表格,而是在下一次运行的时候如果有旧的删掉,没有旧的,重新建表格
(3)update 只是根据映射文件去和数据库中的表对应起来,如果不一致,就更新表的结构
(4)validate 校验映射文件和数据库中的表是不是能对应起来,不能对应报错,实际中常用 注:在使用的时候必须要慎重,我就是在当时学习的时候所设置的属性是validate,所以只要改了数据库名就会抛初始化异常,当时我郁闷了半天都不知道是怎么回事,没有往这方面想,后来才知到balidate是在没有数据库名的时候不让你创建,会抛异常的
当hibernate不和Spring一起使用时要建立 类.hbm.xml与Hibernate.cfg.xml相对应
如下单独使用Hibernate
5.1 导入相关Jar包:Hibernate模式不只是自己内部实现,同样也导入了许多外部的jar包,下面是Hibernate3.6.0框架的基本jar包
我使用的是mysql数据库,可以根据自己使用的数据库添加相关驱动Jar包
5.2 先创建一个User实体
1 package com.a_helloworld; 2 3 public class User { 4 5 private int id; 6 private String name; 7 public int getId() { 8 return id; 9 } 10 public void setId(int id) { 11 this.id = id; 12 } 13 public String getName() { 14 return name; 15 } 16 public void setName(String name) { 17 this.name = name; 18 } 19 20 @Override 21 public String toString() { 22 return "User [id=" + id + ", name=" + name + "]"; 23 } 24 25 26 }
5.3 配置User实体在数据库表的映射user.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.a_helloworld">
<!-- 属性table 表示在数据库中的表名 -->
<class name="User" table="user_1" >
<id name="id" column="id" type="int">
<!-- 值native表示会根据数据库来创建不同的主键生成策略 -->
<generator class="native"></generator>
</id>
<property name="name" column="name" type="string"></property>
</class>
</hibernate-mapping>
5.4 简单配置hibernate.cfg.xml配置文件,这个文件名可以随便修改(xxx.cfg.xml),但是没多大意义,一般不建议修改。配置的信息如下:
1 <!DOCTYPE hibernate-configuration PUBLIC 2 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 3 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 4 5 <hibernate-configuration> 6 <session-factory name="foo"> 7 8 <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 9 <property name="connection.username">root</property> 10 <property name="connection.password">123456</property> 11 <property name="connection.url">jdbc:mysql:///user</property> 12 13 <!-- 要根据自己使用的数据库来配置相对应的属性,也成方言,针对不同数据库 14 关于怎么配置可以查看HibernateAPI 15 --> 16 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 17 18 <!-- Hibernate 創建的SQL語句会显示在控制台 --> 19 <property name="hibernate.show_sql">true</property> 20 21 <!-- 选择方案,常用值:validate | update | create | create-drop --> 22 <property name="hbm2ddl.auto">update</property> 23 24 <mapping resource="com/a_helloworld/user.hbm.xml"/> -- 导入实体映射配置,程序每次启动都会自动检索 25 26 </session-factory> 27 </hibernate-configuration>
以上Hibernate简单配置已经基本完成,可以添加一个测试类来测试是否成功
package com.a_helloworld; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.Session; import org.junit.Test; public class Demo { private static SessionFactory sf = new Configuration()// .configure("hibernate.cfg.xml")// .buildSessionFactory(); @Test public void addUser(){ Session session = null; Transaction tran = null; try{ session = sf.openSession(); // 创建一个Session tran = session.beginTransaction(); //开启事务 User user = new User(); user.setName("张三"); session.save(user); tran.commit();//事务提交 }catch(Exception e){ tran.rollback(); //事务回滚 throw(e); }finally{ session.close(); //关闭session } } @Test public void getUser(){ Session session = null; Transaction tran = null; try{ session = sf.openSession(); // 创建一个Session tran = session.beginTransaction(); //开启事务 /*这里指明你要获得哪个类型,Hibernate会根据类名查询映射配置文件到数据库查询哪张表,根据指定 * id查询实体,通过反射机制创建实体对象 */ User user = (User) session.get(User.class, 1); //执行查询,get tran.commit();//事务提交 }catch(Exception e){ tran.rollback(); //事务回滚 throw(e); }finally{ session.close(); //关闭session } } @Test public void updateUser(){ Session session = null; Transaction tran = null; try{ session = sf.openSession(); // 创建一个Session tran = session.beginTransaction(); //开启事务 User user = new User(); user.setId(1);//这里指定了要更新的数据id为1 user.setName("李四");// 把名字 “张三” 修改为 “李四” session.update(user);//执行更新 tran.commit();//事务提交 }catch(Exception e){ tran.rollback(); //事务回滚 throw(e); }finally{ session.close(); //关闭session } } @Test public void deleteUser(){ Session session = null; Transaction tran = null; try{ session = sf.openSession(); // 创建一个Session tran = session.beginTransaction(); //开启事务 User user = new User(); user.setId(1);//这里指定了要更新的数据id为1 session.delete(user); //执行删除 tran.commit();//事务提交 }catch(Exception e){ tran.rollback(); //事务回滚 throw(e); }finally{ session.close(); //关闭session } } }