Hibernate框架(一)

Hibernate是一个ORM(对象/关系映射)持久化框架

ORM思想:将关系数据库中表中的记录映射成为对象,把对数据库操作转化为对对象的操作。

Hibernate对象持久化操作

保存:把对象永久保存到数据库中。

更新:更新数据库中对象(记录)的状态。

删除:从数据库中删除一个对象。

查询:根据特定的查询条件,把符合查询条件的一个或多个对象从数据库加载到内存中。

加载:根据特定的OID(唯一标志号通常主键),把一个对象从数据库加载到内存中。

 

Hibernate开发步骤

创建Hibernate配置文件

在应用的 classpath 下创建hibernate.cfg.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC

		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

		"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

	<session-factory>
    
		<!-- 配置连接数据库的基本信息 -->
		<property name="connection.username">root</property>
		<property name="connection.password">123456</property>
		<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="connection.url">jdbc:mysql:///testu</property>
		
		<!-- 配置 hibernate 的基本信息 -->
		<!-- hibernate 所使用的数据库方言 -->
		<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>		
		
		<!-- 执行操作时是否在控制台打印 SQL -->
		<property name="show_sql">true</property>
	
		<!-- 是否对 SQL 进行格式化 -->
		<property name="format_sql">true</property>
	
		<!-- 指定自动生成数据表的策略 -->
		<property name="hbm2ddl.auto">update</property>
		
		<!-- 指定关联的 .hbm.xml 文件 -->
		<mapping resource="com/hibernate/helloworld/News.hbm.xml"/>
	
	</session-factory>

</hibernate-configuration>

 

创建持久化 Java 类

1 提供一个无参的构造器

2 提供一个标识属性(identifier property): 通常映射为数据库表的主键字段. 如果没有该属性,一些功能将不起作用,如:Session.saveOrUpdate()

3 为类的持久化类字段声明访问方法(get/set)

4 使用非 final 类: 在运行时生成代理是 Hibernate 的一个重要的功能. 如果持久化类没有实现任何接口, Hibnernate 使用 CGLIB 生成代理. 如果使用的是 final 类, 则无法生成 CGLIB 代理.

5 重写 eqauls 和 hashCode 方法: 如果需要把持久化类的实例放到 Set 中(当需要进行关联映射时), 则应该重写这两个方法

6 持久化类继承任何父类或实现接口,这可以保证代码不被污染。

创建对象-关系映射文件

映射文件的扩展名为 .hbm.xml

1 指定类和表的映射

2 指定持久化类的OID 和表的主键的映射

3 映射类的属性和表的字段

4 指定对象标识符(主键)生成器, 负责为 OID 生成唯一标识符

通过 Hibernate API 编写访问数据库的代码

public static void main(String[] args) {

//1. 创建 Configuration 对象: 对应 hibernate 的基本配置信息和 对象关系映射信息

Configuration configuration = new Configuration().configure();

//2. 创建一个 ServiceRegistry 对象: hibernate 4.x 新添加的对象

//hibernate 的任何配置和服务都需要在该对象中注册后才能有效.

ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())

                            .buildServiceRegistry();

//3.通过serviceRegistry生成sessionFactory

SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

//4. 创建一个 Session 对象

Session session = sessionFactory.openSession();



//5. 开启事务

Transaction transaction = session.beginTransaction();

//6. 执行保存操作

News news = new News("Java12345", "ATGUIGU", new Date(new java.util.Date().getTime()));

session.save(news);

//7. 提交事务

transaction.commit();

//8. 关闭 Session

session.close();

//9. 关闭 SessionFactory 对象

sessionFactory.close();

}

Configuration 类

Configuration 类负责管理 Hibernate 的配置信息,包括:

Hibernate 运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件)。

持久化类与数据表的映射关系(*.hbm.xml 文件)

创建 Configuration 的两种方式

方式一(对应hibernate.properties或者hibernate.cfg.xml):

Configuration cfg = new Configuration().configure();

方式二:Configuration cfg = new Configuration().configure(file);

SessionFactory 接口

针对单个数据库映射关系经过编译后的内存镜像,是线程安全的。

SessionFactory是生成Session的工厂,Hibernate4 新增了一个 ServiceRegistry 接口,所有基于 Hibernate 的配置或者服务都必须统一向这个 ServiceRegistry  注册后才能生效

Hibernate4 中创建 SessionFactory :

//1). 创建 Configuration 对象: 对应 hibernate 的基本配置信息和 对象关系映射信息

Configuration configuration = new Configuration().configure();

//2 hibernate 的任何配置和服务都需要在该对象中注册后才能有效.

ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())

                            .buildServiceRegistry();

//3 根据serviceRegistry创建sessionfactory

SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

Session

Session 是应用程序与数据库之间交互操作的一个单线程对象。Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久层操作的数据都缓存在 session 对象处。相当于 JDBC 中的 Connection。

取得持久化对象的方法: get() load()

持久化对象都得保存,更新和删除:save(),update(),saveOrUpdate(),delete()

开启事务: beginTransaction().

管理 Session 的方法:isOpen(),flush(), clear(), evict(), close()等

 

Hibernate 把对象分为 4 种状态: 持久化状态, 临时状态, 游离状态, 删除状态. Session 的特定方法能使对象从一个状态转换到另一个状态.

Session 缓存可减少 Hibernate 应用程序访问数据库的频率。

临时对象:

1在使用代理主键的情况下, OID为null;

2不在session缓存中

3 数据库也没有

持久化对象:

1 OID不为null  

2在session缓存中

3若数据库记录在,持久化对象和数据库中的相关记录对应

4 Session 在 flush 缓存时, 会根据持久化对象的属性变化, 来同步更新数据库

5在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象

游离对象:

1 OID 不为 null

2不再处于 Session 缓存中

删除对象:

1 在数据库中没有和其 OID 对应的记录

2 不再处于 Session 缓存中

 

Transaction(事务)

代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。

Transaction tx = session.beginTransaction();

常用方法:

commit():提交相关联的session实例

rollback():撤销事务操作

wasCommitted():检查事务是否提交

Hibernate 主键生成策略

flush

Session 按照缓存中对象的属性变化来同步更新数据库,默认情况下 Session 在以下时间点刷新缓存:1显式调用 Session 的 flush() 方法 2当应用程序调用 Transaction 的 commit()方法的时, 该方法先 flush ,然后在向数据库提交事务

当应用程序执行一些查询(HQL, Criteria)操作时,如果缓存中持久化对象的属性已经发生了变化,会先 flush 缓存,以保证查询结果能够反映持久化对象的最新状态

flush 缓存的例外情况: 如果对象使用 native 生成器生成 OID, 那么当调用 Session 的 save() 方法保存对象时, 会立即执行向数据库插入该实体的 insert 语句.

commit() 和 flush() 方法的区别:flush 执行一系列 sql 语句,但不提交事务;commit 方法先调用flush() 方法,然后提交事务. 意味着提交事务意味着对数据库操作永久保存下来。

 

设定刷新缓存的时间点

setFlushMode() 方法显式设定 flush 的时间点

数据库的隔离级别

脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.

不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.

幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.

 

数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题.

一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱

 

4 种事务隔离级别:

Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE. Oracle 默认的事务隔离级别为: READ COMMITED

Mysql 支持 4 中事务隔离级别. Mysql 默认的事务隔离级别为: REPEATABLE READ

 

在 Hibernate 中设置隔离级别

hibernate.connection.isolation 属性来设置事务的隔离级别

1. READ UNCOMMITED

2. READ COMMITED

4. REPEATABLE READ

8. SERIALIZEABLE

Session 数据操作

save()和persist() 方法使一个临时对象转变为持久化对象(当 News 对象处于持久化状态时, 不允许程序随意修改它的 ID)。

区别:当对一个 OID 不为 Null 的对象执行 save() 方法时, 会把该对象以一个新的 oid 保存到数据库中;  但执行 persist() 方法时会抛出一个异常.

 

get() 和 load() 方法都可以根据跟定的 OID 从数据库中加载一个持久化对象。

区别:当数据库中不存在与 OID 对应的记录时, load() 方法抛出 ObjectNotFoundException 异常, 而 get() 方法返回 null;load 方法支持延迟加载策略。而 get 不支持。

 

update() 方法使一个游离对象转变为持久化对象, 并且计划执行一条 update 语句.当修改了 News 对象的属性时, 才执行 update() 语句, 可以把映射文件中 <class> 元素的 select-before-update 设为 true. 该属性的默认值为 false

当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常

当 update() 方法关联一个游离对象时, 如果在数据库中不存在相应的记录, 也会抛出异常.

 

saveOrUpdate() 方法同时包含了 save() 与 update() 方法的功能

 

merge() 方法:

 

delete() 方法既可以删除一个游离对象, 也可以删除一个持久化对象,使对象进入删除状态。

hibernate.use_identifier_rollback 属性, 其默认值为 false, 若把它设为 true, 将改变 delete() 方法的运行行为, delete() 方法会把持久化对象或游离对象的 OID 设置为 null, 使它们变为临时对象

Hibernate 调用存储过程

Work 接口: 直接通过 JDBC API 来访问数据库的操作

Session 的 doWork(Work) 方法用于执行 Work 对象指定的操作, 即调用 Work 对象的 execute() 方法. Session 会把当前使用的数据库连接传递给 execute() 方法.

Public interface Work{

//通过JDBCAPI访问数据库

public void execute(Connection connection) throws SQLException;

}

Session 的 doWork(Work) 方法用于执行 Work 对象指定的操作, 即调用 Work 对象的 execute() 方法. Session 会把当前使用的数据库连接传递给 execute() 方法.

session.doWork(new Work() {



@Override

public void execute(Connection connection) throws SQLException {

   //调用存储过程.

               String proceducer=”{call testProcedure}”;

               CallableStatement cstmt=connection.prepareCall(proceducer);

   Cstmt.executeUpdate();

}

});

Hibernate 与触发器协同工作

出现问题:

1 触发器使 Session 的缓存中的持久化对象与数据库中对应的数据不一致:触发器运行在数据库中, 它执行的操作对 Session 是透明的

2 Session 的 update() 方法盲目地激发触发器: 无论游离对象的属性是否发生变化, 都会执行 update 语句, 而 update 语句会激发数据库中相应的触发器

解决方案:

1 在执行完 Session 的相关操作后, 立即调用 Session 的 flush() 和 refresh() 方法, 迫使 Session 的缓存与数据库同步(refresh() 方法重新从数据库中加载对象)

2 在映射文件的的 <class> 元素中设置 select-before-update 属性: 当 Session 的 update 或 saveOrUpdate() 方法更新一个游离对象时, 会先执行 Select 语句, 获得当前游离对象在数据库中的最新数据, 只有在不一致的情况下才会执行 update 语句

POJO 类和数据库的映射文件*.hbm.xml

hibernate-mapping

类层次:class 主键:id  基本类型:property   实体引用类: many-to-one  |  one-to-one

集合:set | list | map | array one-to-many many-to-many

子类:subclass | joined-subclass

其它:component | any 等

查询语句:query(用来放置查询语句,便于对数据库查询的统一管理和优化)

 

hibernate-mapping(根元素)

schema: 指定所映射的数据库schema的名称。若指定该属性, 则表明会自动添加该 schema 前缀

catalog:指定所映射的数据库catalog的名称。  

default-cascade(默认为 none): 设置hibernate默认的级联风格. 若配置 Java 属性, 集 合映射时没有指定 cascade 属性, 则 Hibernate 将采用此处指定的级联风格.   

default-access (默认为 property): 指定 Hibernate 的默认的属性访问策略。默认值为 property, 即使用 getter, setter 方法来访问属性. 若指定 access, 则 Hibernate 会忽略 getter/setter 方法, 而通过反射访问成员变量.

default-lazy(默认为 true): 设置 Hibernat morning的延迟加载策略. 该属性的默认值为 true, 即启用延迟加载策略. 若配置 Java 属性映射, 集合映射时没有指定 lazy 属性, 则 Hibernate 将采用此处指定的延迟加载策略

auto-import (默认为 true): 指定是否可以在查询语言中使用非全限定的类名(仅限于本 映射文件中的类)。

package (可选): 指定一个包前缀,如果在映射文档中没有指定全限定的类名, 就使用 这个作为包名。

 

Class(指定类和表的映射)

name:指定该持久化类映射的持久化类的类名

table:指定该持久化类映射的表名, Hibernate 默认以持久化类的类名作为表名

dynamic-insert: 若设置为 true, 表示当保存一个对象时, 会动态生成 insert 语句, insert 语句中仅包含所有取值不为 null 的字段. 默认值为 false

dynamic-update: 若设置为 true, 表示当更新一个对象时, 会动态生成 update 语句, update 语句中仅包含所有取值需要更新的字段. 默认值为 false

select-before-update:设置 Hibernate 在更新某个持久化对象之前是否需要先执行一次 查询. 默认值为 false

batch-size:指定根据 OID 来抓取实例时每批抓取的实例数.

lazy: 指定是否使用延迟加载.  

mutable: 若设置为 true, 等价于所有的 <property> 元素的 update 属性为 false, 表 示整个实例不能被更新. 默认为 true.

discriminator-value: 指定区分不同子类的值. 当使用 <subclass/> 元素来定义持久化类 的继承关系时需要使用该属性

 

在对象-关系映射文件中, <id> 元素用来设置对象标识符. <generator> 子元素用来设定 标识符生成器.

Hibernate 提供了标识符生成器接口: IdentifierGenerator, 并提供了各种内置实现

 

 

Id(设定持久化类的 OID 和表的主键的映射)

name: 标识持久化类 OID 的属性名  

column: 设置标识属性所映射的数据表的列名(主键字段的名字).

unsaved-value:若设定了该属性, Hibernate 会通过比较持久化类的 OID 值和该属性值 来区分当前持久化类的对象是否为临时对象

type:指定 Hibernate 映射类型. Hibernate 映射类型是 Java 类型与 SQL 类型的桥梁. 如果没有为某个属性显式设定映射类型, Hibernate 会运用反射机制先识别出持久化类 的特定属性的 Java 类型, 然后自动使用与之对应的默认的 Hibernate 映射类型

Java 的基本数据类型和包装类型对应相同的 Hibernate 映射类型. 基本数据类型无法 表达 null, 所以对于持久化类的 OID 推荐使用包装类型

 

主键生成策略generator

property 元素用于指定类的属性和表的字段的映射

index: 指定一个字符串的索引名称. 当系统需要 Hibernate 自动建表时, 用于为该属性 所映射的数据列创建索引, 从而加快该数据列的查询.

length: 指定该属性所映射数据列的字段的长度

scale: 指定该属性所映射数据列的小数位数, 对 double, float, decimal 等类型的数据列 有效.

formula:设置一个 SQL 表达式, Hibernate 将根据它来计算出派生属性的值.

派生属性: 并不是持久化类的所有属性都直接和表的字段匹配, 持久化类的有些属性的 值必须在运行时通过计算才能得出来, 这种属性称为派生属性

使用 formula 属性时,formula=“(sql)” 的英文括号不能少;Sql 表达式中的列名和表 名都应该和数据库对应, 而不是和持久化对象的属性对应;如果需要在 formula 属性中 使用参数, 这直接使用 where cur.id=id 形式, 其中 id 就 是参数, 和当前持久化对 象的 id 属性对应的列的 id 值将作为参数传入.

 

 

Hibernate 配置项:

Hibernate配置文件:

hibernate.properties、hibernate.cfg.xml

 

hbm2ddl.auto

create : 根据 .hbm.xml  文件来生成数据表并且删除上次的表

create-drop : 根据 .hbm.xml 文件生成表,当SessionFactory一关闭, 表就自动删除

update : 根据 .hbm.xml 文件生成表, 当 .hbm.xml  和数据库中对应的数据表的表结 构不同, Hiberante将更新数据表结构,但不会删除已有的行和列

validate : 比较.hbm.xml和数据库中表列,若 .hbm.xml 定义列在数据表中不存在,则 抛出异常

format_sql:格式化sql

 

C3P0 数据库连接池属性

hibernate.c3p0.max_size: 数据库连接池的最大连接数

hibernate.c3p0.min_size: 数据库连接池的最小连接数

hibernate.c3p0.timeout: 连接对象在多长时间没有使用过后,就应该被销毁

hibernate.c3p0.max_statements:  缓存 Statement 对象的数量

hibernate.c3p0.idle_test_period:  表示连接池检测线程多长时间检测一次池内的所有链 接对象是否超时.

hibernate.c3p0.acquire_increment: 当数据库连接池中的连接耗尽时, 同一时刻获取多 少个数据库连接

hibernate.jdbc.fetch_size:实质是调用 Statement.setFetchSize() 方法设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数。

hibernate.jdbc.batch_size:设定对数据库进行批量删除,批量更新和批量插入的时候的 批次大小。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流光影下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值