初学hibernate的童鞋,刚开应该都有这种感觉,hibernate的配置文件好麻烦,还不如jdbc访问数据库呢,直接写代码,多方便,用hibernate还要写代码,还要写配置,太麻烦了。至少我刚开始学习的时候就是这么想的。配置文件确实有他枯燥的一面,但等你真正深入学习的时候,你就可以发现他枯燥的背后却藏着很多强大的功能,呵呵,让我说的这么玄乎,那就让我们一起来看看吧,让我们一起来见证一下这些配置文件的强大。
Hibernate中配置主要分为两种:一种包含了Hibernate与数据库的基本连接信息,在Hibernate工作的初始阶段,这些信息被先后加载到Configuration和SessionFactory实例;另一种包含了Hibernate的基本映射信息,即系统中每一个类与其对应的数据库表之间的关联信息,在Hibernate工作的初始阶段,这些信息通过hibernate.cfg.xml的mapping节点被加载到Configuration和SessionFactory实例。这两种文件信息包含了Hibernate的所有运行期参数。下面我们用详细的例子来说明这两种文件的基本结构和内容。
实现包含了Hibernate与数据库的基本连接信息的配置方式有两种方式:
第一种是使用hibernate.properties文件作为配置文件。
第二种是使用hibernate.cfg.xml文件作为配置文件。
1. 使用hibernateproperties作为配置文件
对于hibernate.properties作为配置文件的方式,比较适合于初学者。因为初学者往往很难记住xml配置文件的格式,以及需要配置哪些属性。在Hibernate发布包的etc路径下,提供了一个hibernate.properties文件,该文件列出了Hibernate 的所有属性。每个配置段都给出了大致的注释,用户只要取消所需配置段的注释,就可以快速配置Hibernate和数据库的链接此处给出使用hibernate.properties文件创建Configuration对象的方法。
//实例化configuration对象
Configuration cfg = new Configuration()
//多次调用addResource()方法,添加映射文件
cfg.addResource("Item.hbm.xml")
cfg.addResource("Bid.hbm.xml");
查看hibernate.properties文件发现,该文件没有提供Hibernate映射文件的方式。因此使用hibernate.properties文件来作为配置文件时,必须使用Configuration的.addResource()方法,使用该方法来添加映射文件。
注意:正如上面的代码所示,使用hibernate.properties文件配置Hibernate的属性固然简单,但是因为要手动添加映射文件,当映射文件极其多时,这是一件非常催人泪下的事情。这也就是在实际开发中,不常使用hibernate.properties文件作为配置文件的原因。
当然还有另一种添加配置文件的策略,因为映射文件和持久化类是一一对应的,可以通过Configuration对象来添加持久化类,让Hibernate自己来搜索映射文件。
//实例化configuration对象
Configuration cfg = new Configuration()
//多次调用addClass()方法,直接添加持久化类
cfg .addClass(ppp.Item.class)
cfg .addClass(ppp.BId.class);
2. 使用hibernate.cfg.xml作为配置文件
关于xml配置形式,我感觉也没必要多说什么。下面的一个例子足以把这种配置说明清楚,下面我们一起来看一个带有详细注释的hibernate.cfg.xml文件:
- <!--标准的XML文件的起始行,version='1.0'表明XML的版本,encoding='gb2312'表
- 明XML文件的编码方式-->
- <?xml version='1.0'encoding='gb2312'?>
- <!--表明解析本XML文件的DTD文档位置,DTD是DocumentType 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">com.mysql.jdbc.Driver</property>
- <!--设置数据库的连接url:jdbc:mysql://localhost/hibernate,其中localhost表示mysql服务器名称,此处为本机,hibernate是数据库名-->
- <property name="hibernate.connection.url"> jdbc:mysql://localhost/hibernate</property>
- <!--连接数据库是用户名-->
- <property name="hibernate.connection.username">root</property>
- <!--连接数据库是密码-->
- <property name="hibernate.connection.password">123456</property>
- <!--数据库连接池的大小-->
- <propertynamepropertyname="hibernate.connection.pool.size">20</property>
- <!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于差错,程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。项目部署后可
- 以设置为false,提高运行效率-->
- <propertynamepropertyname="hibernate.show_sql">true</property>
- <!--jdbc.fetch_size是指Hibernate每次从数据库中取出并放到JDBC的Statement中的记录条数。FetchSize设的越大,读数据库的次数越少,速度越快,Fetch Size越小,读数据库的次数越多,速度越慢-->
- <propertynamepropertyname="jdbc.fetch_size">50</property>
- <!--jdbc.batch_size是指Hibernate批量插入,删除和更新时每次操作的记录数。BatchSize越大,批量操作的向数据库发送Sql的次数越少,速度就越快,同样
- 耗用内存就越大-->
- <propertynamepropertyname="jdbc.batch_size">23</property>
- <!--jdbc.use_scrollable_resultset是否允许Hibernate用JDBC的可滚动的结果集。对分页的结果集。对分页时的设置非常有帮助-->
- <propertynamepropertyname="jdbc.use_scrollable_resultset">false</property>
- <!--connection.useUnicode连接数据库时是否使用Unicode编码-->
- <propertynamepropertyname="Connection.useUnicode">true</property>
- <!--connection.characterEncoding连接数据库时数据的传输字符集编码方式,最好设置为gbk,用gb2312有的字符不全-->
- <propertynamepropertyname="connection.characterEncoding">gbk</property>
- <!--hibernate.dialect 只是Hibernate使用的数据库方言,就是要用Hibernate连接那种类型的数据库服务器。-->
- <property name="hibernate.dialect">
- org.hibernate.dialect.MySQLDialect</property>
- <!-是否自动创建数据库表 他主要有一下几个值:
- validate:当sessionFactory创建时,自动验证或者schema定义导入数据库。
- create:每次启动都drop掉原来的schema,创建新的。
- create-drop:当sessionFactory明确关闭时,drop掉schema。
- update(常用):如果没有schema就创建,有就更新。
- -->
- <propertynamepropertyname="hbm2ddl.auto">create</property>
- <!配置此处 sessionFactory.getCurrentSession()可以完成一系列的工作,当调用时,
- hibernate将session绑定到当前线程,事务结束后,hibernate
- 将session从当前线程中释放,并且关闭session。当再次调用getCurrentSession
- ()时,将得到一个新的session,并重新开始这一系列工作。-->
- <propertynamepropertyname="current_session_context_class">thread</property>
- <!--指定映射文件为“hibernate/ch1/UserInfo.hbm.xml”-->
- <mappingresourcemappingresource="org/mxg/UserInfo.hbm.xml">
- </session-factory>
- </hibernate-configuration>
以上应该是大部分常用的配置文件属性,当然里面的很多部分都是可以在配置hibernate开发环境时自动生成的,刚开始的时候还是建议大家手动的去配置一下,可以达到熟悉的的时候在用自动生成
下面我们继续看一下包含了Hibernate的基本映射信息的配置文件,也就是系统中每一个类与其对应的数据库表之间的关联信息,这种配置文件一般命名为:类名.hbm.xml,下面我们通过一个具体的代码示例来看一下类名.hbm.xml的结构:
- <span xmlns="http://www.w3.org/1999/xhtml" style=""><?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>
- <class name="com.bzu.hibernate.Student" table="student">
- <id name="id" column="id" type="string">
- <generator class="uuid"></generator>
- </id>
- <property name="name" column="name" type="string"></property>
- <property name="cardId" column="cardId"type="string"></property>
- <property name="age" column="age" type="int"></property>
- <set name="courses" table="student_course" cascade="save-update">
- <key column="stu_id"></key>
- <many-to-many class="com.bzu.hibernate.Course" column="course_id">
- </many-to-many>
- </set>
- </class>
- </hibernate-mapping></span>
下面我们一个个标签进行讲解一下:
1.hibernate-mapping
这个元素包括一些可选的属性。schema和catalog属性,指明了这个映射所连接(refer)的表所在的schema和/或catalog名称。假若指定了这个属性,表名会加上所指定的schema和catalog的名字扩展为全限定名。假若没有指定,表名就不会使用全限定名。 default-cascade指定了未明确注明cascade属性的Java属性和集合类Hibernate会采取什么样的默认级联风格。auto- import属性默认让我们在查询语言中可以使用非全限定名的类名。
- <span xmlns="http://www.w3.org/1999/xhtml" style=""><hibernate-mapping
- schema="schemaName" (1)
- catalog="catalogName" (2)
- default-cascade="cascade_style" (3)
- default-access="field|property|ClassName" (4)
- default-lazy="true|false" (5)
- auto-import="true|false" (6)
- package="package.name" (7)
- /></span>
(1) schema ( 可选 ): 数据库 schema 的名称。
(2) catalog ( 可选 ): 数据库 catalog 的名称。
(3) default-cascade ( 可选 - 默认为 none): 默认的级联风格。
(4) default-access ( 可选 - 默认为 property): Hibernate 用来访问所有属性的策略。可以通过实现 PropertyAccessor 接口 自定义。
(5) default-lazy ( 可选 - 默认为 true): 指定了未明确注明 lazy 属性的 Java 属性和集合类, Hibernate 会采取什么样的默认加载风格
(6) auto-import ( 可选 - 默认为 true): 指定我们是否可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。
(7) package ( 可选 ): 指定一个包前缀,如果在映射文档中没有指定全限定的类名,就使用这个作为包名。
2.class
使用 class 元素来定义一个持久化类:
- <span xmlns="http://www.w3.org/1999/xhtml" style=""><class
- name="ClassName" (1)
- table="tableName" (2)
- discriminator-value="discriminator_value" (3)
- mutable="true|false" (4)
- schema="owner" (5)
- catalog="catalog" (6)
- proxy="ProxyInterface" (7)
- dynamic-update="true|false" (8)
- dynamic-insert="true|false" (9)
- select-before-update="true|false" (10)
- polymorphism="implicit|explicit" (11)
- where="arbitrary sql where condition" (12)
- persister="PersisterClass" (13)
- batch-size="N" (14)
- optimistic-lock="none|version|dirty|all" (15)
- lazy="true|false" (16)
- entity-name="EntityName" (17)
- check="arbitrary sql check condition" (18)
- rowid="rowid" (19)
- subselect="SQL expression" (20)
- abstract="true|false" (21)
- node="element-name"
- /></span>
(1) name ( 可选 ): 持久化类(或者接口)的 Java 全限定名。如果这个属性不存在, Hibernate 将假定这是一个非 POJO 的实体映射。
(2) table ( 可选 - 默认是类的非全限定名 ): 对应的数据库表名。
(3) discriminator-value ( 可选 - 默认和类名一样 ): 一个用于区分不同的子类的值,在多态行为时使用。它可以接受的值包括 null 和 not null 。
(4) mutable ( 可选,默认值为 true): 表明该类的实例是可变的或者不可变的。
(5) schema ( 可选 ): 覆盖在根 <hibernate-mapping> 元素中指定的 schema 名字。
(6) catalog ( 可选 ): 覆盖在根 <hibernate-mapping> 元素中指定的 catalog 名字。
(7) proxy ( 可选 ): 指定一个接口,在延迟装载时作为代理使用。 你可以在这里使用该类自己的名字。
(8) dynamic-update ( 可选 , 默认为 false): 指定用于 UPDATE 的 SQL 将会在运行时动态生成,并且只更新那些改变过的字段。
(9) dynamic-insert ( 可选 , 默认为 false): 指定用于 INSERT 的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。
(10) select-before-update ( 可选 , 默认为 false): 指定 Hibernate 除非确定对象真正被修改了(如果该值为 true -译注),否则不会执行 SQL UPDATE 操作。在特定场合(实际上,它只在一个瞬时对象( transient object )关联到一个新的 session 中时执行的 update() 中生效),这说明 Hibernate 会在 UPDATE 之前执行一次额外的 SQL SELECT 操作,来决定是否应该执行 UPDATE 。
(11) polymorphism (多态) ( 可选 , 默认值为 implicit ( 隐式 ) ): 界定是隐式还是显式的使用多态查询(这只在 Hibernate 的具体表继承策略中用到-译注)。
(12) where ( 可选 ) 指定一个附加的 SQLWHERE 条件, 在抓取这个类的对象时会一直增加这个条件。
(13) persister ( 可选 ): 指定一个定制的 ClassPersister 。
(14) batch-size ( 可选 , 默认是 1) 指定一个用于根据标识符( identifier )抓取实例时使用的 "batch size" (批次抓取数量)。
(15) optimistic-lock (乐观锁定) ( 可选,默认是 version): 决定乐观锁定的策略。
(16) lazy ( 可选 ): 通过设置 lazy="false" , 所有的延迟加载( Lazyfetching )功能将被全部禁用( disabled )。
(17) entity-name ( 可选,默认为类名 ): Hibernate3 允许一个类进行多次映射(前提是映射到不同的表),并且允许使用 Maps 或 XML 代替 Java 层次的实体映射(也就是实现动态领域模型,不用写持久化类-译注)。
(18) check ( 可选 ): 这是一个 SQL 表达式,用于为自动生成的 schema 添加多行( multi-row )约束检查。
(19) rowid ( 可选 ):Hibernate 可以使用数据库支持的所谓的 ROWIDs ,例如: Oracle 数据库,如果你设置这个可选的 rowid , Hibernate 可以使用额外的字段 rowid 实现快速更新。 ROWID 是这个功能实现的重点,它代表了一个存储元组( tuple )的物理位置。
(20) subselect ( 可选 ): 它将一个不可变( immutable )并且只读的实体映射到一个数据库的子查询中。当你想用视图代替一张基本表的时候,这是有用的,但最好不要这样做。更多的介绍请看下面内容。
(21) abstract ( 可选 ): 用于在 <union-subclass> 的继承结构( hierarchies )中标识抽象超类。
3.id
被映射的类必须定义对应数据库表主键字段。大多数类有一个JavaBeans风格的属性,为每一个实例包含唯一的标识。<id> 元素定义了该属性到数据库表主键字段的映射。
- <id
- name="propertyName" (1)
- type="typename" (2)
- column="column_name" (3)
- unsaved-value="null|any|none|undefined|id_value" (4)
- access="field|property|ClassName" (5)
- length="L" (6)
- <generatorclassgeneratorclass="generatorClass"/>
- </id>
(1) name (可选): 标识属性的名字。
(2) type (可选): 标识Hibernate类型的名字。(如果没配置,hibernate将会自动转化成相应的数据库类型)
(3) column (可选 - 默认为属性名): 主键字段的名字。
(4) unsaved-value (可选 - 默认为一个切合实际(sensible)的值): 一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。这可以把这种实例和从以前的session中装载过(可能又做过修改--译者注)但未再次持久化的实例区分开来。
(5) access (可选 - 默认为property): Hibernate用来访问属性值的策略。
(6)length="L"指定长度
4. Generator
可选的<generator>子元素是一个Java类的名字,用来为该持久化类的实例生成唯一的标识。如果这个生成器实例需要某些配置值或者初始化参数,用<param>元素来传递。
- <id name="id"type="long" column="cat_id">
- <generatorclassgeneratorclass="org.hibernate.id.TableHiLoGenerator">
- <paramnameparamname="table">uid_table</param>
- <paramnameparamname="column">next_hi_value_column</param>
- </generator>
- </id>
所有的生成器都实现 org.hibernate.id.IdentifierGenerator 接口。这是一个非常简单的接口;某些应用程序可以选择提供他们自己特定的实现。当然, Hibernate 提供了很多内置的实现。
下面是一些内置生成器的快捷名字:
increment
用于为 long, short 或者 int 类型生成唯一标识。只有在没有其他进程往同一张表中插入数据时才能使用。在集群下不要使用。
identity
对 DB2,MySQL, MS SQL Server, Sybase 和 HypersonicSQL 的内置标识字段提供支持。返回的标识符是 long, short 或者 int 类型的。 sequence
在 DB2,PostgreSQL, Oracle, SAP DB, McKoi 中使用序列( sequence) ,而在 Interbase 中使用生成器 (generator) 。返回的标识符是 long, short 或者 int 类型的。
hilo
使用一个高 / 低位算法高效的生成 long, short 或者 int 类型的标识符。给定一个表和字段(默认分别是 hibernate_unique_key 和 next_hi )作为高位值的来源。高 / 低位算法生成的标识符只在一个特定的数据库中是唯一的。
seqhilo
使用一个高 / 低位算法来高效的生成 long, short 或者 int 类型的标识符,给定一个数据库序列( sequence) 的名字。
uuid
用一个 128-bit 的 UUID 算法生成字符串类型的标识符,这在一个网络中是唯一的(使用了 IP 地址)。 UUID 被编码为一个 32 位 16 进制数字的字符串。
guid
在 MS SQL Server 和 MySQL 中使用数据库生成的 GUID 字符串
native
根据底层数据库的能力选择 identity, sequence 或者 hilo 中的一个
assigned
让应用程序在 save() 之前为对象分配一个标示符。这是 <generator> 元素没有指定时的默认生成策略。手动分配主键的时候要设置成它
select
通过数据库触发器选择一些唯一主键的行并返回主键值来分配一个主键。
foreign
使用另外一个相关联的对象的标识符。通常和 <one-to-one> 联合起来使用。
5. property
<property> 元素为类定义了一个持久化的 ,JavaBean 风格的属性。
- <span xmlns="http://www.w3.org/1999/xhtml" style=""><property
- name="propertyName" (1)
- column="column_name" (2)
- type="typename" (3)
- update="true|false" (4)
- insert="true|false" (4)
- formula="arbitrary SQL expression"(5)
- access="field|property|ClassName"(6)
- lazy="true|false" (7)
- unique="true|false" (8)
- not-null="true|false" (9)
- optimistic-lock="true|false" (10)
- generated="never|insert|always" (11)
- node="element-name|@attribute-name|element/@attribute|."
- index="index_name"
- unique_key="unique_key_id"
- length="L"
- precision="P"
- scale="S"
- />
- </span>
(1) name: 属性的名字 , 以小写字母开头。
(2) column ( 可选 - 默认为属性名字 ): 对应的数据库字段名。也可以通过嵌套的 <column> 元素指定。
(3) type ( 可选 ): 一个 Hibernate 类型的名字。
(4) update, insert ( 可选 - 默认为 true) : 表明用于 UPDATE 和 / 或 INSERT 的 SQL 语句中是否包含这个被映射了的字段。这二者如果都设置为 false 则表明这是一个 “ 外源性( derived ) ” 的属性,它的值来源于映射到同一个(或多个)字段的某些其他属性,或者通过一个 trigger( 触发器)或其他程序生成。
(5) formula ( 可选 ): 一个 SQL 表达式,定义了这个计算( computed )属性的值。计算属性没有和它对应的数据库字段。
(6) access ( 可选 - 默认值为 property): Hibernate 用来访问属性值的策略。
(7) lazy ( 可选 - 默认为 false): 指定指定实例变量第一次被访问时,这个属性是否延迟抓取( fetched lazily )( 需要运行时字节码增强)。
(8) unique ( 可选 ): 使用 DDL 为该字段添加唯一的约束。 同样,允许它作为 property-ref 引用的目标。
(9) not-null ( 可选 ): 使用 DDL 为该字段添加可否为空( nullability )的约束。
(10) optimistic-lock ( 可选 - 默认为 true): 指定这个属性在做更新时是否需要获得乐观锁定( optimistic lock )。换句话说,它决定这个属性发生脏数据时版本( version )的值是否增长。
(11) generated ( 可选 - 默认为 never): 表明此属性值是否实际上是由数据库生成的。
typename可以是如下几种:
Hibernate 基本类型名(比如: integer, string, character,date, timestamp,float, binary, serializable, object, blob )。
一个 Java 类的名字,这个类属于一种默认基础类型 ( 比如: int, float,char, java.lang.String, java.util.Date,java.lang.Integer, java.sql.Clob) 。
一个可以序列化的 Java 类的名字。
一个自定义类型的类的名字。(比如: com.illflow.type.MyCustomType) 。
基本值类型 (Hibernate 内建立自己的类型 , 从 java 转化成数据库类型 ) string :从 java.lang.String 到 VARCHAR ( 或者 Oracle 的 VARCHAR2) 的映射。
date, time, timestamp :从 java.util.Date 和其子类到 SQL 类型 DATE, TIME 和 TIMESTAMP ( 或等价类型 ) 的映射。
calendar, calendar_date :从 java.util.Calendar 到 SQL 类型 TIMESTAMP 和 DATE( 或等价类型 ) 的映射。
big_decimal, big_integer :从 java.math.BigDecimal 和 java.math.BigInteger 到 NUMERIC ( 或者 Oracle 的 NUMBER 类型 ) 的映射。
locale, timezone, currency :从 java.util.Locale, java.util.TimeZone 和 java.util.Currency 到 VARCHAR ( 或者 Oracle 的 VARCHAR2 类型 ) 的映射 . Locale 和 Currency 的实例被映射为它们的 ISO 代码。 TimeZone 的实例被影射为它的 ID 。
Class :从 java.lang.Class 到 VARCHAR ( 或者 Oracle 的 VARCHAR2 类型 ) 的映射。 Class 被映射为它的全限定名。
Binary :把字节数组 (byte arrays) 映射为对应的 SQL 二进制类型。
Text :把长 Java 字符串映射为 SQL 的 CLOB 或者 TEXT 类型。
Serializable :把可序列化的 Java 类型映射到对应的 SQL 二进制类型。你也可以为一个并非默认为基本类型的可序列化 Java 类或者接口指定 Hibernate 类型 serializable 。
clob, blob : JDBC 类 java.sql.Clob 和 java.sql.Blob 的映射。某些程序可能不适合使用这个类型,因为 blob 和 clob 对象可能在一个事务之外是无法重用的。 ( 而且 , 驱动程序对这种类型的支持充满着补丁和前后矛盾。 )