Hibernate配置文件
一、概述:
1、Hibernate配置文件主要用于配置数据库连接和Hibernate运行时所需的各种属性
2、每个Hibernate配置文件对应一个Cconfiguration对象
3、Hibernate配置文件可以有两种格式:
1)hibernate.properties
2)hibernate.cfg.xml
二、hibernate.cfg.xml的常用属性:
1、JDBC连接属性:
1)hibernate.connection.driver_class:数据库驱动
2)hibernate.connection.url:数据库的url
3)hibernate.connection.username:数据库用户名
4)hibernate.connection.password:数据库密码
5)dialect:配置数据库的方言,根据底层的数据库不同产生不同的sql语句,Hibernate会针对数据库的特性在访问时进行优化
2、C3P0数据库连接池属性:
1)hibernate.c3p0.max_size:最大连接数
2)hibernate.c3p0.min_size:最小连接数
3)hibernate.c3p0.acquire_increment:当数据库连接池中的连接耗尽时,同一时刻获取多少个数据库连接
4)hibernate.c3p0.timeout:连接池中连接对象在多长时间没有使用过后,就应该被销毁
5)hibernate.c3p0.idle_test_period:表示连接池检测线程多长时间检测一次池内的所有连接对象是否超时,连接池本身不会把自己从连接池中移除
而是专门有一个线程按照一定的时间间隔来做这件事,这个线程通过比较连接对象最后一次呗使用和当前时间的时间差来和timout做对比,进而决定是否销
毁这个连接对象。
6)hibernate.c3p0.max_statements:缓存Statement对象的数量
三、在hibernate.cfg.xml中配置C3P0:
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.acquire_increment">2</property>
<property name="hibernate.c3p0.timeout">2000</property>
<property name="hibernate.c3p0.idle_test_period">2000</property>
<property name="hibernate.c3p0.max_statements">10</property>
四、hibernate.cfg.xml的其他属性:
1、show_sql:是否将运行时生成的sql语句输出到日志以供调试。取值为true|false
2、format_sql:是否将sql转化为格式良好的sql。取值为true|false
3、hbm2ddl.auto:在启动和停止时自动的创建、更新或删除数据库模式。取值为create|update|create-drop|validate
4、hibernate.jdbc.fetch_size:实质是调用Statement.setFetchSize()方法设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数。
例如:一次查询1万条记录,对于Oracle的JDBC驱动来说,是不会1次性把1万条记录取出来,而只会取出fetchSize条记录,当结果集遍历完了这些记录以后再去数据库中取fetchSize条数据。因此大大节省了无谓的内存消耗。fetchSize设的越大,读数据库的次数越少,速度越快,反之fetchSize越小,读数据库的次数越多,速度越慢。Oracle数据库的JDBC驱动默认的fetchSize=10,这是个保守的设定。根据测试,当fetchSize=50时,性能会提升1倍,当fetchSize=100时,性能还能继续提升20% ,fetchSize继续增大时,性能提升的就不显著了,并不是所有的数据库都支持fetchSize特性,例如mysql就不支持
5、hibernate。jdbc.batch_size:设定对数据库进行批量删除、批量更新、批量插入时的批次大小(类似缓冲区的大小)。batch_size越大,批量操作时向数据库发送的sql越少,速度就越快。
测试显示:当batch_size=0时,使用hibernate对oracle数据库删除1万条记录需要25秒
当batch_size=50时,使用hibernate对oracle数据库删除1万条记录需要5秒
对于oracle数据库batch_size=30是比较合适的
五、POJO类和数据库的映射文件*.hbm.xml
-- POJO类和关系数据库之间的映射可以用一个XML文档来定义
-- 通过POJO类的数据库映射文件,Hibernate可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据库表列之间的对应关系
-- 在运行时Hibernate将根据这个映射文件来生成各种SQL语句
-- 映射文件的扩展名为 .hbm.xml
1、hibernate-mapping:是Hibernate映射文件的根元素
1)schema:指定所映射的数据库schema的名称。若指定该属性,则表明会自动添加该schema前缀
2)catalog:指定所映射的数据库的catalog的名称
3)default-cascade(默认为none):设置hibernate默认的级联风格。若配置Java属性,集合映射时没有指定cascade属性,则Hibernate将采用此处指定的级联风格。
4)default-access(默认为property):指定Hibernate的默认的属性访问策略。默认值为property,即使用getter/setter方法来访问属性;若指定access,则Hibernate会忽略getter/setter方法,而通过反射访问成员变量
5)default-lazy(默认为true):设置Hibernate moming的延迟加载策略,该属性的默认值为true,即启用延迟加载策略,若配置为Java属性映射,集合映射时没有指定lazy属性,则Hibernate将采用此处指定的延迟加载策略
6)auto-import(默认为true):指定是否可以在查询语语音中使用非全限定的类名(仅限于本地映射文件中的类)
7)package(可选):指定一个包前缀,如果在映射文档中没有指定全限定的类名,就使用这个作为包名
2、class:
1)name:指定该持久化类映射的持久化类的类名
2)table:指定该持久化类映射的表名,Hibernate默认以持久化类的类名作为表名
3)dynamic-insert:若设置为true,表示当保存一个对象时会动态生成insert语句,insert语句中仅包含所有取值不为null的字段,默认值为false
4)dynamic-update:若设置为true,表示当更新一个对象时,会动态生成update语句,update语句中仅包含所有取值需要更新的字段,默认值为false
5)select-before-update:设置Hibernate在更新某个持久化对象之前是否需要先执行一次查询,默认值为false
6)batch-size:指定根据OID来抓取实例时每批抓取的实例数
7)lazy:指定是否使用延迟加载
8)mutable:若设置为true,等价于所有的<property>元素的update属性为false,表示整个实例不能被更新,默认值为true
9)discriminator-value:指定区分不同子类的值,当使用<subclass/>元素来定义持久化类的继承关系时需要使用该属性
3、id(映射对象标识符):
1)Hibernate使用对象标识符(OID)来建立内存中的对象和数据库表中记录的对应关系。对象的OID和数据表的主键对应Hibernate通过标识符生成器来为主键赋值
2)Hibernate推荐在数据表中使用代理主键,即不具备业务含义的字段。代理主键通常为整型类型,因为整数比字符串类型要节省更多的数据库空间。
3)在对象-关系映射文件中,<id>元素用来设置对象标识符。<generator>子元素用来设定标识符生成器
4)Hibernate提供了标识符生成器接口:IdentifierGenerator,并提供了各种内置实现
4、generator主键生成器:
1)increment标识符生成器:由Hibernate以递增的方式为代理主键赋值,Hibernate会先读取表中的主键的最大值,而接下来向表中插入记录时,就在max(id)的基础上递增,增量为1
适用范围:
-- 由于increment生成标识符机制不依赖于底层数据库系统,因此它适合所有的数据库系统。
-- 适用于只有单个Hibernate应用进程访问同一个数据库的场合,在集合群环境下不推荐适用它
-- OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会抛出异常
特点:跨数据库,不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。
2)identity标识符生成器:由底层数据库来负责生成标识符,它要求底层数据库把主键定义为自动增长字段类型
适用范围:
-- 由于identity生成标识符的机制依赖于底层数据库系统,因此,要求底层数据库系统必须支持自动增长字段类型。支持自动增长字段类型的数据库包括:DB2、Mysql、SqlServer、Sybase等
-- OID必须为long、int或short类型,如果把OID定义为byte类型在运行时会抛出异常
3)sequence标识符生成器:利用底层数据库提供的序列来生成标识符
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="sequence">
<param name="sequence">news_seq</param>
</generator>
</id>
-- Hibernate在持久化一个类对象时,先从底层数据库的news_seq序列中获得一个唯一的标识符,再把它作为主键值
适用范围:
-- 由于sequence生成标识符的机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列。支持序列的数据库包括:DB2、Oracle等
-- OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会抛出异常
4)assigned:主键由外部程序负责生成,在 save() 之前必须指定一个。Hibernate不负责维护主键生
成。与Hibernate和底层数据库都无关,可以跨数据库。在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免。
<id name="id" column="id">
<generator class="assigned" />
</id>
特点:可以跨数据库,人为控制主键生成,应尽量避免。
5)hilo:hilo(高低位方式high low)是hibernate中最常用的一种生成方式,需要一张额外的表保存hi的值。保存hi值的表至少有一条记录(只与第一条记录有关),否则会出现错误。可以跨数据库。
<id name="id" column="id">
<generator class="hilo">
<param name="table">hibernate_hilo</param>
<param name="column">next_hi</param>
<param name="max_lo">100</param>
</generator>
</id>
<param name="table">hibernate_hilo</param> 指定保存hi值的表名
<param name="column">next_hi</param> 指定保存hi值的列名
<param name="max_lo">100</param> 指定低位的最大值
也可以省略table和column配置,其默认的表为hibernate_unique_key,列为next_hi
<id name="id" column="id">
<generator class="hilo">
<param name="max_lo">100</param>
</generator>
</id>
hilo生成器生成主键的过程(以hibernate_unique_key表,next_hi列为例):
(1) 获得hi值:读取并记录数据库的hibernate_unique_key表中next_hi字段的值,数据库中此字段值加1保存。
(2) 获得lo值:从0到max_lo循环取值,差值为1,当值为max_lo值时,重新获取hi值,然后lo值继续从0到max_lo循环。
(3) 根据公式 hi * (max_lo + 1) + lo计算生成主键值。
注意:当hi值是0的时候,那么第一个值不是0*(max_lo+1)+0=0,而是lo跳过0从1开始,直接是1、2、3……
那max_lo配置多大合适呢?这要根据具体情况而定,如果系统一般不重启,而且需要用此表建立大量的主键,可以吧max_lo配置大一点,这样可以减少读取数据表的次数,提高效率;反之,如果服务器经常重启,可以吧max_lo配置小一点,可以避免每次重启主键之间的间隔太大,造成主键 值主键不连贯。
特点:跨数据库,hilo算法生成的标志只能在一个数据库中保证唯一。
6)native:native由hibernate根据使用的数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式,灵活性很强。如果能支持identity则使用identity,如果支持sequence则使用sequence。
<id name="id" column="id">
<generator class="native" />
</id>
例如MySQL使用identity,Oracle使用sequence
注意:如果Hibernate自动选择sequence或者hilo,则所有的表的主键都会从Hibernate默认的sequence或hilo表中取。并且,有的数据库对于默认情况主键生成测试的支持,效率并不是很高。使用sequence或hilo时,可以加入参数,指定sequence名称或hi值表名称等,如
<param name="sequence">hibernate_id</param>
特点:根据数据库自动选择,项目中如果用到多个数据库时,可以使用这种方式,使用时需要设置表的自增字段或建立序列,建立表等。
7)uuid:(Universally Unique Identifier),是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字,标准的UUID格式为:
xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字。
<id name="id" column="id">
<generator class="uuid" />
</id>
Hibernate在保存对象时,生成一个UUID字符串作为主键,保证了唯一性,但其并无任何业务逻辑意义,只能作为主键,唯一缺点长度较大,32位(Hibernate将UUID中间的“-”删除了)的字符串,占用存储空间大,但是有两个很重要的优点,Hibernate在维护主键时,不用去数据库查询,从而提高效率,而且它是跨数据库的,以后切换数据库极其方便。
特点:uuid长度大,占用空间大,跨数据库,不用访问数据库就生成主键值,所以效率高且能保证唯一性,移植非常方便,推荐使用。
8)foreign:使用另外一个相关联的对象的主键作为该对象主键。主要用于一对一关系中。
<id name="id" column="id">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<one-to-one name="user" class="domain.User" constrained="true" />
该例使用domain.User的主键作为本类映射的主键。
特点:很少使用,大多用在一对一关系中。
4、property:用于指定类的属性和表的字段的映射
1)name:指定该持久类的属性的名字
2)column:指定与类的属性映射的表的字段名。如果没有设置该属性。Hibernate将直接使用类的属性名作为字段名
3)type:指定Hibernate映射类型。Hibernate映射型是Java类型和SQL类型的桥梁。如果没有为某个属性显式设定映射类型。Hibernate会运用反射机制先识别出持久化类的特定属性Java类型,然后自动使用与之对应的默认的Hibernate映射类型
4)not-null:若该属性值为true,表明不允许为null,默认为false
5)access:指定Hibernate的默认的属性访问策略。默认为property,即使用getter/setter方法来访问属性。若指定field,则Hibernate会忽略getter/setter方法,而通过反射访问成员变量
6)unique:设置是否为该属性所映射的数据列添加唯一的约束
5、映射Java的日期、时间类型:
1)在Java中,代表时间和日期的类型包括java.util.Date和java.util.Calendar.此外,在JDBC API中还提供了3个扩展了java.uti.Date类的子类:java.sql.Date、java.sql.Time、java.sql.Timestamp这三个雷分别和标准SQL类型中的DATE、TIME、TIMESTAMP类型对应
2)在标准SQL中,DATE类型表示日期,TIME表示时间、TIMESTAMP表示时间戳同时包含日期和时间信
3)如何把java.util.Date映射为DATE、TIME、TIMESTAMP:
例如:
<property name="date" type="timestamp">
<column name="DATE" />
</property>
<property name="date" type="time">
<column name="DATE" />
</property>
<property name="date" type="date">
<column name="DATE" />
</property>
其中timestamp、time、date既不是Java类型也不是标准SQL类型,而是Hibernate映射类型(建议java定义时使用java.util.Date类型)
6、Java大对象类型的Hibernate映射
1)在java中,java.lang.String可用于表示长字符串(长度超过255),字节数组byte[]可用于存放图片或文件的二进制数据。此外,在JDBC API中还提供了java.sql.Clob和java.sql.Blob类型,它们分别和标准SQL中的CLOB和BLOB类型对应。CLOB表示字符串大对象(Character Large Object),BLOB表示二进制对象(Binary Large Object)
2)mysql不支持标准SQL的CLOB类型,在mysql中,用TEXT、MEDIUMTEXT及java.lang.String或java.sql.Clob
3)实际上在java应用程序中处理长度超过255的字符串,使用java.lang.String比java.sql.Clob更方便
例如:
<!-- 若需要精确映射,可使用sql-type类型 -->
<!-- 映射大文本 -->
<property name="content">
<column name="content" sql-type="mediumtext"></column>
</property>
<!-- 映射二进制 -->
<property name="image">
<column name="image" sql-type="mediumblob"></column>
</property>
保存图片到数据库中:
@Test
public void testBlob() throws IOException{
News news = new News();
news.setTitle("AA");
news.setDate(new Date());
news.setContent("DDDDD");
news.setAuthor("java");
InputStream stream = new FileInputStream("123.png");
Blob image = Hibernate.getLobCreator(session)
.createBlob(stream, stream.available());
news.setImage(image);
session.save(news);
}
从数据库中获取图片:
News news = (News)session.get(News.class,4);
Blob image = news.getImage();
InputStream in = image.getBinaryStream();
System.out.println(in.available());