Hibernate配置文件:
主要用于配置数据库和Hibernate运行时需要的各种属性
每一个配置文件对应一个Configuration对象
<hibernate-configuration>
<session-factory>
<!--链接数据库的基本信息-->
<property name="connection.username">root</property>
<property name="connection.passwrod">123456</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc://mysql://localhost:3306/dbname</property>
<!--配置hibernate的基本信息-->
<!--hibernate所使用的数据库方言,告诉hibernate数据库的方言,可以到hibernate.properties找需要的方言-->
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<!--执行操作时是否在控制台打印sql语句-->
<property name="show_sql">true</property>
<!--是否对sql语句进行格式化-->
<property name="format_sql">true</property>
<!--
指定生成数据表的策略
create:每次都重新生成数据表
create-drop:从创建表用用完了就直接删除
update:(最常用)如果表不存在,就创建,若hbm.xml文件和表结构不同,将会更新表结构,但不影响已有的行和列
validate:会与数据库表进行比较,若hbm.xml文件中的列在数据表中不存在,则抛出异常
-->
<property name="hbm2ddl">update</property>
<!--设置Hibernate的事务隔离级别
1-READ UNCOMMITED
2-READ COMMITED
3-EEPEATABLEREAD
4-SERIALIZEABLE
-->
<property name="connection.isolation">2</property>
<!--删除对象后使其OID为null-->
<property name="use_identifier_rollback">true</property>
<!--配置C3P0数据源-->
<property name="hibernate.c3p0.max_size">100</property>
<property name="hibernate.c3p0.min_size">10</property>
<property name="c3p0.acquire_increment">5</property>
<property name="hibernate.c3p0.idle_test_period">2000</property>
<property name="c3p0.timeout">2000</property>
<property name="c3p0.max_statement">10</property>
<!--设定JDBC的Statement读取数据库时每次从数据库取出的记录条数,该值应该折中取值不过大也不过小,注意:对Orcle有效,但是MYSQL无效-->
<property name="hibernate.jdbc.fetch_size">100</property>
<!--设定数据库进行批量删除,批量更新,批量插入的时候的批次大小,折中取值,注意:对Orcle有效,但是MYSQL无效-->
<property name="hibernate.jdbc.batch_size">10</property>
<!--指定关联的映射文件-->
<mapping resource="com/.../映射文件名.hbm.xml"/>
</session-factory>
</hibernate-configuration>
<hibernate-mapping package="">
<!--持久化类必须提供一个无参构造器,getset方法-->
<class name="全类名" table="表名">
<id name="id" type="数据类型">
<column name="ID"/>
<!--指定主键的生成方式
increment:以递增的方式为代理主键赋值,先读取表中主键的最大值,最大值+1生成一个主键,
有并发问题;
identity:由底层数据库来负责生成,要求底层数据库把主键定义为自动增长字段类型long,int,short,
支持的数据库包括:DB2 MySQL,MySQLserver等;
sequence:利用底层数据库提供的序列来生成标识符,要求底层数据库必须支持序列,
支持的有:DB2,Oracle等,MySQL不支持。OID必须为long,int,short;
hilo:Hibernate会按照一种high/low算法生成标识符。
它从数据库的特定表的字段获取high值,不依赖于热河底层数据库。
native:根据底层数据库对自动生成标识符的能力来选择使用identity,sequence或者Hilo。
-->
<generator class="native"/>
</id>
<!--
update="true":该列的值不能被修改
-->
<property name="属性名" type="属性名的数据类型", update="true">
<column name="对应表的字段名"/>
</property>
<!--映射Java的时间日期类型
因为java.util.Date是java.sql.Date,java.sql.Time,java.sql.Timestamp的父类,
所以java.util.Date可以对应SQL类型的DATE,TIME,TIMESTAMP,通过property的type属性进行映射。
-->
<!--timestamp,time,date不是Java类型。也不是标准SQL类型,而是Hibernate映射类型-->
<property name="date" type="timestamp">
<column name="DATE"></column>
</property>
<!--映射组成关系-->
<component name="pay" class="">
<property></property>
</component>
</class>
</hibernate-mapping>
//1.创建一个SessionFactory对象
SessionFactory sessionFactory = null;
//1).创建Configuration对象,对应hibernate的基本配置信息和对象关系映射信息
Configuration configuration = new Configuration().configure("/hibernate.cfg.xml");
//2).创建一个ServiceRegistry,hibernate的任何配置和服务都需要在该对象中注册后才有效
ServiceRegistry serviceRegistry =
new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
//2.创建一个session对象
Session session = sessionFactory.openSession();
//3.开启事务
Transaction transaction = session.beginTransaction();
//4.执行操作
session.save(new Object());
//5.提交事务
transaction.commit();
//6.关闭session
session.clear();
//7.关闭sessionFactory对象
sessionFactory.close();
session概述
1、Session是hibernate向应用程序提供操作数据库的最主要的接口,提供了基本的保存,更新,删除和加载Java对象的方法。
2、session具有一个缓存,位于缓存中的对象乘坐持久化对象,它和数据库的相关记录对应。Session能够某些时间点,按照缓存中的对象变化来执行相关的SQL语句来同步更新数据库,这个过程被称为刷新缓存(flush)
3、站在持久化的角度,hibernate把对象分为4种状态:持久化状态、临时状态、游离状态、删除状态。Session的特定方法能使对象从一个状态转换到另一个状态。
Hibernate一级缓存
1、在Session接口的实现种包含了一系列的Java集合,这些Java集合构成了session缓存,只要session实例没有结束生命周期,且没有清理缓存,则放在session缓存里的对象也不会结束生命周期。
2、Session缓存可减少Hibernate应用程序访问数据的频率
- -
Session的缓存操作
1)、flush方法:当调用该方法的时候,会强制使数据库的记录与缓存中的对象保持同步,可能会发送相应的SQL语句,但不会提交事务。在Transaction的commit方法中,会先调用session的flush方法,再提交事务。
注意:在未提交事务或者显示条用flush方法之前,也可能会进行flush操作。
1)、执行HQL或QBC查询,会先执行flush操作,以得到最新的记录数据。
2)、若记录的id是由底层数据库使用自增的方式生成的,则在调用save方法后会立即发送insert语句,保证对象的id使存在的。
2)、refresh方法:强制使缓存中的记录与数据库的数据状态保持一致,换句话就是强制发送一条select语句得到最新数据的状态
3)、clear方法:清理session里的所有缓存
数据库的隔离级别
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,会导致各种并发问题。
1、脏读:对于两个事务t1,t2,t1读取了已经被t2更新但还没有提交的字段之后,若t2回滚,t1读取的数据就是临时且无效的。
2、不可重复读:对于两个事务t1,t2,t1读取了一个字段后,然后t2更新了该字段,之后T1再次读取同一个字段,值就不同了。
3、幻读:对于两个事务T1,T2,T1从一个表中读取了一个字段,然后该表中插入了新的行,之后T1再次读取同一个表,就会出现多出几行。
数据库的事务隔离性,数据库必须是具有隔离并发运行各个事务的能力,使它们不会相互影响。
在Hibernate中设置隔离级别:
JDBC数据库连接使用数据库系统默认的隔离级别。在Hibernate的配置文件中可以显示的设置隔离级别,每一个隔离级别对应一个整数;
1-READ UNCOMMITED
2-READ COMMITED
3-EEPEATABLEREAD
4-SERIALIZEABLE
Hibernate通过hibernate映射文件来指定hibernate.connection.isolation属性来设置事务的隔离级别
持久化对象的状态
1、持久化状态,也叫托管
OID不为null
位于session缓存中
若在数据库中已有和其对应的记录,持久化对象和数据库中的记录对应
在同一个session实例的缓存中,数据库表的每条记录只能对应唯一的持久化对象
2、临时状态
在使用代理主键的情况下,OID通常为null
不处于session的缓存中
在数据库中没有对应的记录
3、游离状态,也叫脱管
OID不为null
不再处于session的缓存中
一般情况下,游离对象是由持久化对象转变过来的,因此在数据库中可能还有与其对应的记录
4、删除状态
数据库中没有和其OID对应的记录
不再处于session的缓存中
一般情况下,应用程序不该再使用该删除对象
Session的核心方法
save()和persist()方法区别
save()方法使一个临时对象变为持久化对象,为对象分配ID,在 flush 缓存时会发送一条 INSERT 语句. 在 save 方法之前的 id 是无效的 持久化对象的 ID 是不能被修改的!
persist()和 save() 的区别 :
在调用 persist 方法之前, 若对象已经有 id 了, 则不会执行 INSERT, 而抛出异常
get()和load()的区别
get方法会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据库中没有就返回null
load方法根据映射文件上类级别的lazy属性的配置(默认为true):
①若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
②若为false,就跟Hibernate的get方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException,所说的load方法抛异常是指在使用该对象的数据时,数据库中不存在该数据时抛异常,而不是在创建这个对象时
update()方法
1、若更新一个持久化对象,不需要显示调用update方法,因为在调用transaction的commit方法
时会先执行session的flush方法。
2、更新一个游离对象需要显示调用session的update方法,可以吧一个游离对象变成持久化对象
需要注意:
1、无论要更新的游离对象和数据表的记录是否一致,都会发送update语句。
如何不盲目发送update语句:在.hbm.xml文件的class的节点设置select-before-update="true"
默认为false,但通常不需要设置该属性,因为对多发送select语句。
2、若数据表没有对应的记录,但还调用了update语句,会抛出异常
3、当update方法关联一个游离对象时。如果在session缓存中已经存在相同OID的持久化对象,会抛出异常,因为在session缓存中不能有两个OID相同的对象。、
saveOrUpdate()方法
同时包含了save方法和update方法的功能。在保存一个对象时。判断OID是否为null来决定执行save还是update,注意:1、若OID不为null,但数据表中没有对应的记录,会抛出异常
delete()方法
只要OID与数据表中的某条记录一致,就会删除该条记录,若OID没有在数据表中有记录,则会抛出异常,可以通过设置HIbernate配置文件的hibernate.use_identifier_rollback为true使删除对象后使其OID为null
evict()方法
从session缓存中把指定的持久化对象移除
doWork()方法
如果需要使用原生的Connection操作数据库
session.doWork(new Work(){
@Override
public void execute(Connection connection) whrows SQLException{
//批量操作等可以使用原生操作
}
});
在Hibernate中使用C3P0数据源
hibernate.c3p0.max_size:数据库连接池最大的连接数
hibernate.c3p0.min_size:数据库连接池最小的连接数
hibernate.c3p0.acquire_increment:当数据库连接池中的连接耗尽时,同一时刻获取多少个数据库连接
hibernate.c3p0.idle_test_period:连接池检测线程多长时间检测一次池内的所有连接对象是否超时,连接池本身不会把自己从连接池中移除,而是专门有一个线程按照一定的时间间隔来做这件事,这个线程通过比较连接对象最后一次被使用的时间和当前时间差来和timeout做对比,进而决定是否销毁这个连接对象。
hibernate.c3p0.timeout;数据库连接池中的连接对象在多长时间没有使用后,应该被销毁
hibernate.c3p0.max_statement:缓存Statement对象的数量