hibernate 总结
hibernate 简介:
hibernate是一个开源框架,它是对象关联关系映射的框架,它对JDBC做了轻量级的封装,而我们java程序员可以使用 面向对象的思想来操纵数据库,提高生产效率。
orm:是一种思想 对象关系映射
hibernate核心接口
session:负责被持久化对象CRUD操作
sessionFactory:负责初始化hibernate,创建session对象
configuration:负责配置并启动hibernate,创建SessionFactory
Transaction:负责事物相关的操作
Query和Criteria接口:负责执行各种数据库查询
hibernate工作原理:
1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的<mapping resource="com/xx/User.hbm.xml"/>读取并解析映射信息
3.通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory
4.Session session = sf.openSession();//打开Sesssion
5.Transaction tx = session.beginTransaction();//创建并启动事务Transation
6.persistent operate操作数据,持久化操作
8.关闭Session
9.关闭SesstionFactory
为什么要用hibernate:
1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
对象的三种状态
瞬时 没id,没关联
持久 有id,有关联
游离 有id,没有关联
Hibernate是如何延迟加载?get与load的区别
1. 对于Hibernate get方法,Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据 库中没有就返回null。
2. Hibernate load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),分情况讨论:
(1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生
成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
(2)若为false,就跟Hibernateget方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
这里get和load有两个重要区别:
如果未能发现符合条件的记录,Hibernate get方法返回null,而load方法会抛出一个ObjectNotFoundException。
load方法可返回没有加载实体数据的代 理类实例,而get方法永远返回有实体数据的对象。
总之对于get和load的根本区别,一句话,hibernate对于 load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方 法,hibernate一定要获取到真实的数据,否则返回null。
Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都是对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、
说下Hibernate的缓存机制:
Hibernate缓存的作用:
Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据
Hibernate缓存分类:
Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存
Hibernate一级缓存又称为“Session的缓存”,它是内置的,意思就是说,只要你使用hibernate就必须使用session缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。在第一级缓存中,持久化类的每个实例都具有唯一的OID。
Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是可选的,是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件。
缓存
一级缓存 可管理的(查了一次再查第二次 sql不会执行)
一级缓存:也称session缓存,属于线程级
别缓存,该缓存本质就是一个集合该集合被放置到了session对象中,
所以也叫Session缓存。因为session是线程级别的,所以该缓存属于线程级别缓存
查询:1.根据id查询对象
2. ResultSet会被封装成对象,放入缓存以及返回程序。如果缓存中存在要查id的对象,返回缓存中的对象。
修改:
1. 根据id查询对象
2. ResultSet会被封装成对象,一式两份,分别放入se
ssion缓存以及缓存快照中
3. 事务在提交时,会比对session缓存中的以及快照中的对象是否发生变化。如果发生变化执行修改。
二级缓存 (重量级别,对比一级缓存,一启动时 会预编译)
第二类 hibernate的二级缓存---------->(sessionFactory的缓存,是基于进程或集群范围内的缓存,可以被多个session共享
由于SessionFactory的声明周期和程序的声明周期是相同的,并且是单例的
。)
(1)目前已经不适用了 代替技术redis
(2)二级缓存默认是不打开的,需要配置
(3)二级缓存的使用范围是sessionFactory
SessionFactory级别的 可控的 可管理的 要开启
进程或集群范围内的缓存
x 适合放入二级缓存中的数据
很少被修改
不是很重要的数据,允许出现偶尔的并发问题
不适合放入的数据
经常被修改
财务数据,绝对不允许出现并发问题
与其他应用共享的数据
一级缓存 和二级缓存的区别
一级缓存一级缓存是hibernate自带缓存,由系统进行维护和管理。一级缓存生命周期为session范围。当session关闭时,一级缓存中的内容会被清空。二级缓存二级缓存是基于第三方,需要另外引入jar包。由用户手动配置和维护二级缓存。二级缓存生命周期为sessionFactory范围。当sessionFactory关闭时,二级缓存中的内容会被清空。
三级缓存
基于二级缓存 要开启二级缓存 缓存的是id 通过id去查询
查询是数据库技术中常见的操hibernate为查询提供查询缓存,用来提高查询速度,优化查询功能。 若果要使用三级缓存 必须打开二级缓存。三级缓存是基于二级缓存的。缓存的是id 如果不开启二级缓存 将没有意义,因为它还是会从数据库查找。
什么样的数据适合存放到第二级缓存中?
1 很少被修改的数据
2 不是很重要的数据,允许出现偶尔并发的数据
3 不会被并发访问的数据
4 常量数据
不适合存放到第二级缓存的数据?
1经常被修改的数据
2 .绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发
3 与其他应用共享的数据。
Hibernate查找对象如何应用缓存?
当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;如果都查不到,再查询数据库,把结果按照ID放入到缓存
删除、更新、增加数据的时候,同时更新缓存
Hibernate管理缓存实例
无论何时,我们在管理Hibernate缓存(Managing the caches)时,当你给save()、
update()或saveOrUpdate()方法传递一个对象时,或使用
load()、
get()、
list()、
iterate() 或
scroll()方法获得一个对象时, 该对象都将被加入到
Session的内部缓存中。
当随后
flush()方法被调用时,对象的状态会和数据库取得同步。 如果你不希望此同步操作发生,或者你正处理大量对象、需要对有效管理内存时,你可以调用evict() 方法,从一级缓存中去掉这些对象及其集合。
Hibernate的查询方式
Sql、Criteria,
object comptosition
Hql:
1、 属性查询
2、 参数查询、命名参数查询
3、 关联查询
4、 分页查询
5、 统计函数
如何优化Hibernate?
1.使用双向一对多关联,不使用单向一对多
2.灵活使用单向一对多关联
3.不用一对一,用多对一取代
4.配置对象缓存,不使用集合缓存
5.一对多集合使用Bag,多对多集合使用
Set
6. 继承类使用显式多态
7. 表字段要少,表关联不要怕多,有二级缓存撑腰
hibernate的开发步骤:
开发步骤
1)搭建好环境
引入hibernate最小的jar包
准备Hibernate.cfg.xml启动配置文件
2)写实体类(pojo)
3)为实体类写映射文件
"User.hbm.xml"
在hibernate.cfg.xml添加映射的实体
4)创建库表
5)写测试类
获得Configuration
创建SessionFactory
打开
Session
开启事务
使用
session操作数据
提交事务
关闭资源
13.update与saveOrUpdate有什么区别?
save() 方法很显然是执行保存操作的,如果是对一个新的刚new出来的对象进行保存,自然要使用这个方法了,数据库中没有这个对象。
update() 如果是对一个已经存在的托管对象进行更新那么肯定是要使用update()方法了,数据中有这个对象。
saveOrUpdate() 这个方法是更新或者插入,有主键就执行更新,如果没有主键就执行插入。【此方法慎用】
在Hibernate中saveOrUpdate()方法在执行的时候,先会去session中去找存不存在指定的字段,如果存在直接update,否则
save,这个时候问题就发生了。
有两张表,表A和表B,这两张表的主键都是一样的,例如都是MASTER_ID,同时对应的BO里面属性都是masterID,现在要执行的操作是,以 MASTER_ID为条件将表A中的数据查询出来,然后将部分值插入到表B中,然后再更新表B,在查询表A后,session中已经存在masterID 了,这个时候再去对表B进行savaOrUpdate的时候,Hibernate会发现session中已经存在masterID了,所以执行的就是 update,但是实际上表B中根本不存在masterID这个值,当你执行完查询数据库的时候会发现没有插入数据,像这种情况,就得先用 masterID对表B进行查询,当返回的BO为NULL时,new一个新BO然后再进行插入,这个时候用到的就是createbo了。
什么是SessionFactory,她是线程安全么?
SessionFactory 是Hibrenate单例数据存储和线程安全的,以至于可以多线程同时访问。一个SessionFactory 在启动的时候只能建立一次。SessionFactory应该包装各种单例以至于它能很简单的在一个应用代码中储存.
JDBC hibernate 和 ibatis 的区别
jdbc:手动
手动写sql
delete、insert、update要将对象的值一个一个取出传到sql中,不能直接传入一个对象。
select:返回的是一个resultset,要从ResultSet中一行一行、一个字段一个字段的取出,然后封装到一个对象中,不直接返回一个对象。
ibatis的特点:半自动化
sql要手动写
delete、insert、update:直接传入一个对象
select:直接返回一个对象
hibernate:全自动
不写sql,自动封装
delete、insert、update:直接传入一个对象
select:直接返回一个对象
1.入门
a.什么是hibernate
Hibernate是一个持久化框架。
Hibernate是一个ORM框架,它是一个面向Java环境的对象/关系数据库映射工具。
Hibernate是一个轻量级的ORM框架,完全采用普通的Java对象而不必继承Hibernate中的某个超类或者实现某个接口。
Hibernate是面向对象的程序设计语言和关系数据库之间的桥梁,真正实现了采用面向对象的方式操作关系型数据库。
b.快速搭建一个hibernate
1.导包
2.核心配置文件
1.数据库的连接信息
2.额外的配置
3.映射配置
3.映射文件
class属性
property属性
id属性
4.实体类(javabean)
5.测试
2.配置
3.缓存
4.查询
5.注解 过滤器 拦截器
框架的搭建
1.导包
导入lib下面的reqiried下的包
2.准备实体类和映射文件
b.映射配置
在实体类所在的包下新建映射文件 (类名 *.hbm.xml),导入dtd约束
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
apping-3.0.dtd">
配置
<hibernate-mapping>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.znsd.hibernate.Address" table="address_tb">
<id name="aId" column="aId">
<generator class="increment"></generator>
</id>
<property name="province" column="province"></property>
<property name="city" column="city"></property>
</class>
</hibernate-mapping>
a
.核心配置
1.数据源
2.额外配置(方言 sql语句打印 数据库表的生成策略 缓存配置 链接映射)
3.配置核心配置文件 hibernate.cfg.xml.导入约束 hibernate-configuration-3.0.dtd
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
配
置
<session-configuration>
</session-configuration>
<hibernate-configuration>
<session-factory>
<!-- 配置数据库连接信息 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:
mysql://localhost:3306/hibernate?useUnicode=true&
;characterEncoding=utf-8</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- 数据库方言
在MYSQL里面关键字limite只能在MYSQL使用
在Oracle里面实现分页rownum
让hibernate框架识别不同数据库的不同语言
-->
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 在控制台输出sql语句 -->
<property name="show_sql">true</property>
<!-- 格式化sql语句 -->
<property name="format_sql">true</property>
<!-- 数据库生成策略
update:如果没有表就创建 ,有 就更新
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 核心配置映射文件 可以写多个配置文件 -->
<mapping class="com.znsd.hibernate.Student"/>
</session-factory>
</hibernate-configuration>
hibernate-mapping
package属性:填写一个包名
class属性:name属性--->类名(package没有配置name属性要体现出类) table属性--->表名
id属性(映射主键):name属性--->类中主键属性名
column属性:表中主键名,
length属性:当前列长度。默认数据对于类型最大长度
type属性:当前列的类型,不写自动匹配属性类
generator属性:主键生成策略(uuid native)
generator属性的class属性 --》代理主键
increment:先查询表中主键最大值,加1作为新的主键值
identity:依赖于数据库中的主键自增
sequence:使用数据库中的序列
hilo:hibernate自己用高低位算法完成主键自增
uuid:生成随机字符串作为主键
native:(常用) 自动根据数据库 三选一(identity sequence hilo)
property属性(映射普通列)
name:类中主键属性名
colunm属性:表中主键名。默认列名为属性名
length属性:当前列的长度
type属性:当前列的类型。默认自动检测属性类型
blod:字节码存储,存储加密的东西
timeStamp:时间戳 有规律的一串数字 可与date相互转换
lazy:是否启动延迟加载 默认false
组件标签
Hibenrate.cfg.xml 配置文件
<!-- 数据库生成策略
update:如果没有表就创建 ,有 就更新
-->
<property name="hibernate.hbm2ddl.auto">update</property>
create:自动建表,每次启动都会自动建表,即使表已经存在,仍然会删除重新建
create-drop:自动建表,每次启动hiberante都会自动建表,每次运行完成便会将表删除
update:如果没有表就创建 ,有 就更新 如果配置改变,自动改变表结构
validate:不会自动创建表结构,只负责在启动时检验表结构,检测出问题后会抛出异常
集合
array
list
set
map
configuration
config,读取配置文件
buildSessionFactory,创建sessionFactory
Configuration conf=new Configuration().config;
SessionFactory sf=conf.buildSessionFactory;
SessionFactroy
根据配置信心创建session对象
1.SessionFactory创建需要消耗较多的内存资源
2.SessionFactory是线程安全的设计
结论:在一个web项目中确保只有一个SessionFactory存在
//获得一个全新的session
Session session=sf.openSession();
//获得与线程绑定的session ,需要在主配置文件中配置,2.不需要手动关闭session
Session session=getCurrentSession
Session
hibernate中操作数据库的核心对象
1.操作增删改查
2.获得事物操作对象
beginTransaction getTransaction 获取事物对象,开启事物
get load根据给定表示和实体类返回持久化对象的实例
sava 增
delete 删
update 改
savaOrUpdate 根据给定的实例的标识属性的值啦决定增或改
createQuery 根据给定的HQL查询条件创建一个新的Query实例
createCriteria 根据给定的实体的名称,创建一个新的Criteria实例
createSQLQuery 根据给定的SQL查询条件创建一个新的SQLQuery实例
get方法不会应用类级别加载策略,立即加载
load方法会应用类级别加载策略,load方法调用时,不会发送任何SQL语句,返归一个代理对象,使用对象时才执行查询加载数据
Transaction
用于操作事物的对象
session.beginTransaction();
//逻辑代码
session.getTransaction().commit();
session.close();
factory.close();
对象的三种状态
瞬时 没id,没关联
持久 有id,有关联
游离 有id,没有关联
关系映射
一对一 主键 外键
一对多
多对多
缓存
一级缓存 可管理的(查了一次再查第二次 sql不会执行)
一级缓存:也称session缓存,属于线程级别缓存,该缓存本质就是一个集合该集合被放置到了session对象中,所以也叫Session缓存。因为session是线程级别的,所以该缓存属于线程级别缓存
查询:1.根据id查询对象
2. ResultSet会被封装成对象,放入缓存以及返回程序。如果缓存中存在要查id的对象,返回缓存中的对象。
修改:
1. 根据id查询对象
2. ResultSet会被封装成对象,一式两份,分别放入se
ssion缓存以及缓存快照中
3. 事务在提交时,会比对session缓存中的以及快照中的对象是否发生变化。如果发生变化执行修改。
二级缓存 (重量级别,对比一级缓存,一启动时 会预编译)
第二类 hibernate的二级缓存---------->(sessionFactory的缓存,是基于进程或集群范围内的缓存,可以被多个session共享
由于SessionFactory的声明周期和程序的声明周期是相同的,并且是单例的
。)
(1)目前已经不适用了 代替技术redis
(2)二级缓存默认是不打开的,需要配置
(3)二级缓存的使用范围是sessionFactory
SessionFactory级别的 可控的 可管理的 要开启
进程或集群范围内的缓存
x 适合放入二级缓存中的数据
很少被修改
不是很重要的数据,允许出现偶尔的并发问题
不适合放入的数据
经常被修改
财务数据,绝对不允许出现并发问题
与其他应用共享的数据
开启步骤:
1.导包 EHCache
2.开启配置
a.将ehcache.xml文件复制到src目录(可在etc目录找到文件)
3.在hibernate.cfg.xml配置中开启二级缓存
<property name="hibernate.cache.use_second_level_cache">true</property>
4.指定缓存产品
<property name="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
--------------------------------------------------------------------------------------------------------------
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
<hibernate-configuration>
<session-factory>
<!-- 配置数据库连接信息 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:
mysql://localhost:3306/hibernate?useUnicode=true&
;characterEncoding=utf-8</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- 数据库方言
在MYSQL里面关键字limite只能在MYSQL使用
在Oracle里面实现分页rownum
让hibernate框架识别不同数据库的不同语言
-->
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 在控制台输出sql语句 -->
<property name="show_sql">true</property>
<!-- 格式化sql语句 -->
<property name="format_sql">true</property>
<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<!-- 数据库生成策略
update:如果没有表就创建 ,有 就更新
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 核心配置映射文件 可以写多个配置文件 -->
<mapping resource="com\znsd\hibernate\Student.hbm.xml"/>
</session-factory>
</hibernate-configuration>
一级缓存 和二级缓存的区别
一级缓存一级缓存是hibernate自带缓存,由系统进行维护和管理。一级缓存生命周期为session范围。当session关闭时,一级缓存中的内容会被清空。二级缓存二级缓存是基于第三方,需要另外引入jar包。由用户手动配置和维护二级缓存。二级缓存生命周期为sessionFactory范围。当sessionFactory关闭时,二级缓存中的内容会被清空。
三级缓存
基于二级缓存 要开启二级缓存 缓存的是id 通过id去查询
查询是数据库技术中常见的操hibernate为查询提供查询缓存,用来提高查询速度,优化查询功能。 若果要使用三级缓存 必须打开二级缓存。三级缓存是基于二级缓存的。缓存的是id 如果不开启二级缓存 将没有意义,因为它还是会从数据库查找。
<!-- 启动二级缓存查询缓存 -->
<property name="cache.use_query_cache">true</property>
<!– 在代码中也必须手动启动查询缓存-->
query.setCacheable(true);
4.查询
HQL hibernate query language ()
查询的是对象,自动生成sql
a.返归列
当HQL只查询一列数据时,使用当前属性的类型作为List的泛型类型。
String hql = “select name from Student";Query query = session.createQuery(hql);List
<String>
list = query.list();
如果查询返回多个列的数据时,使用Object[]作为List的泛型类型。
String hql = “select name,pass from Student";Query query = session.createQuery(hql);List
<Object[]>
list = query.list();
当HQL返回多列时,可以使用构造器来生成查询结果
String hql = “select new Student(name,pass) from Student";Query query = session.createQuery(hql);List
<Student>
list = query.list();
当查询返回多个列的数据时,使用List作为List的泛型类型。
String hql = “select new List(name,pass) from Student";Query query = session.createQuery(hql);List
<List>
list = query.list();
b.查询条件
通过占位符的方式传递参数
String hql = "from Student where id = ?1 and name=?2";
Query query = session.createQuery(hql);
query.setInteger("1",1); //使用字符串"1"作为占位符
query.setString("2", "张三")
List<Student> list = query.list();
通过命名参数的方式传递参数
String hql = "from Student where id = :id and name = :name";
Query query = session.createQuery(hql);
query.setInteger("id",1);
query.setString("name", "张三");
List<Student> list = query.list();
命名方式传递集合参数
String hql = "from Student where id in(:ids);
Query query = session.createQuery(hql);
query.setParameterList("ids",new Object[]{3,4,5});
List<Student> list = query.list();
命名参数传递like参数
String hql = "from Student where username like :name";
Query query = session.createQuery(hql);
query.setString("name", "张%");
List<Student> list = query.list();
c.返回值
D.批处理
前面已经hibernate给我们提供了update和delete来实现增加和删除,但是当批量修改时,会比较麻烦,而且效率比较低,hql中也可以使用update和delete来实现批量更新和删除。
String hql = "update Student set password = :pass where id=:id";
Query query = session.createQuery(hql);
query.setInteger("id",1);
query.setString("pass", "888888");
int count = query.executeUpdate();
使用hql语句方式是不支持级联操作,所以这里一定要注意。更新之后缓存也没有被更新,所以这种操作要谨慎。
QBC Query By Criterria
好处:在不使用SQL情况下进行查询。完 全对象操控 可调控性高
Criteria criteria = session.createCriteria(Dept.class);
List<Dept> list = criteria.list(); 使用Criteria查询所有的部门
Criteria criteria = session.createCriteria(Dept.class);
criteria = criteria.add(Restrictions.eq("location", "西一区"));
List<Dept> list = criteria.list();添加条件,查询位置在“西一区”的部门
HQL 仿SQL
仿对象
性能中(包装的东西多性能高)
QBC 无SQL
对象
性能低
SQL 纯SQL
无对象
性能高
注解
对应着映射文件
步骤:1.类上面加注解
@Entity
@table
2.id @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column
3 .普通属性 @Column
@Entity
@Table(name="Student")
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column
private Integer sId;
@Column
private Integer studentId;
@Column
private String studentName;
过滤器
多条件重复使用
Hibernate给我们提供了一种针对某个类或者集合使用预先定义的过滤条件(filter criteria)的功能。过滤器用法有点类似数据库中的视图,只是视图是在数据库端定义,而过滤器是在应用程序端定义。过滤条件相当于定义一个类似集合上的”where”属性的条件,但是过滤器可以带参数。
使用过滤器分为三个步骤:定义过滤器,使用
<filter-def />
定义过滤器。使用过滤器,使用
<filter />
应用过滤器。代码中通过session启用过滤器。
<fileter-def />
是hibernate-mapping的子元素
<filter />
是class、集合元素的子元素。
<class name="Student" table="students">
<!-- 使用过滤器 -->
<filter name="nameFilter" condition="s_sex = :sex" />
</class>
<!-- 定义过滤器 -->
<filter-def name="nameFilter">
<filter-param name="sex" type="string"/>
</filter-def>
String hql = "from Student";
Query query = session.createQuery(hql);
//调用过滤器
session.enableFilter("nameFilter").setParameter("sex", "女");
List<Student> list = query.list();
拦截器
要实现拦截器,需要实现Interceptor接口,重写所有方法。由于方法比较多,通常推荐继承EmptyInterceptor类。
全局拦截器配置:通过Configuration进行配置。
Configuration cfg = new Configuration().configure();//全局配置cfg.setInterceptor(new MyInterceptor());
局部拦截器配置:通过Session进行配置。
session = factory.withOptions() .interceptor(new MyInterceptor()).openSession();
