Hibernate介绍
Hibernate是当今主流的java持久层的框架之一,是一个开源的ORM框架,它对JDBC进行了轻量级的对象封装。
优点
- Hibernate对JDBC访问数据库的代码做了封装。简化了数据访问层繁琐的重复性代码。
- Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,很大程度的简化了道层编码工作
- Hibernate使用java的反射机制
- Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系
Hibernate中配置hibernate.cfg.xml的头信息
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
配置详解
orm映射文件
- 用于配置实体和表的对应关系的文件,建议名称使用类名.hbm.xml并且放在和实体相同的包中
hibernate-mapping标签
- 一个orm映射文件只有一个hibernate-mapping标签,在此配置表结构和对象的映射
- package属性用于指定所在的包,那么在配置文件中使用完整的类名的时候,就可以不带包名,但是只会指定到当前包,不会对应其子包。
class标签及其子标签
配置实体与表中的对应关系的
- name属性:设置为实体的完整类名,如果已经在hibernate-mapping中设置了package属性那么就可以只写类名
- table属性:设置为数据库中对应的表名,此表就是要与对象建立映射关系的那个表
- dynamic-insert属性:动态插入 默认值是false,如果设置为true就代表如果字段值为null,不参与insert语句。
- dynamic-update属性:动态更新 默认值false,如果设置为true就代表没改动过的属性,将不会生成到update语句中
generator字标签
用于设置主键的生成策略,配置class属性可以配置不同的主键生成策略
- increment:数据库自己生成主键,先从数据库中查询最大的ID值,将ID值加1作为新的主键
- identity:依赖于数据的主键自增功能
- sequence:序列,依赖于数据中的序列功能(oracle)
- hilo:Hibernate自己实现序列的算法,自己生成主键(hilo算法,只做了解)
- native:自动根据数据库判断,三选一.identity|sequence|hilo
- uuid:生成32位的不重复随机字符串当做主键
- assigned:自己指定主键值.表的主键是自然主键时使用。
property标签
- 配置除了主键之外的普通属性映射
- name属性 : 实体中属性名称
- column属性 : 表中列的名称
- length属性 : 数据长度
- precision属性 : 小数点后的精度
- scale属性 : 有效位数
- insert属性 : 该属性是否加入insert语句.(一般不用)
- update属性 : 该属性是否加入update语句.(一般不用)
- not-null属性 : 指定属性的约束是否使用 非空
- unique属性 : 指定属性的约束是否使用 唯一
- type属性 :表达该属性的类型(一般可以不用设置),可以有三种指定属
- java类型,如 java.lang.String
- 数据库类型指定,如 varchar
- Hibernate类型指定,如 string
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- package:指定包名 -->
<hibernate-mapping package="com.zhiyou.pojo">
<!-- 设置pojo类和表之间的映射关系
name:类名
table:表名 -->
<class name="User" table="user" >
<!-- 属性和字段之间的映射
name:属性名
column:字段名称
如果属性名和字段名称一致时,字段名称可以不写-->
<id name="id" column="id">
<!-- 主键生成策略 -->
<generator class="increment"></generator>
</id>
<property name="name" column="name"></property>
<property name="password"></property>
<property name="age" column="u_age"></property>
</class>
</hibernate-mapping>
hibernate.cfg.xml的配置信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///db_hbm</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 显示sql -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 二级缓存的提供类 在hibernate4.0版本以后我们都是配置这个属性来指定二级缓存的提供类-->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<!-- 二级缓存配置文件的位置 -->
<property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>
<!-- 加载映射文件 -->
<mapping resource="com/zhiyou/pojo/User.hbm.xml"/>
<mapping class="com.zhiyou.pojo.Student"/>
<mapping class="com.zhiyou.pojo.Teacher"/>
<mapping class="com.zhiyou.pojo.Room"/>
<mapping class="com.zhiyou.pojo.Course"/>
</session-factory>
</hibernate-configuration>
API详解
增删改查
--- 查询数据: session.get(类名.class,id)
---增加数据: session.save(对象)
---删除数据: session.delete(对象)
---修改数据: session.update(对象)
hibernate对象的状态
----hibernate中的对象有3种状态,分别为瞬时状态,持久态,托管态
- 瞬时态(transient),无OID,new对象还没有交给session管理
- 持久态(persistent),有OID,加入到session中,且session并没有关闭,在数据库中有对应的记录
- 托管态(detached),也叫游离态,有OID但是和session没有关联,session关闭后
状态的转变
- 创建对象即为瞬时态
- 瞬时态转换为持久态调用save()或者saveOrUpdate()
- 瞬时态转换为游离态设置OID属性值
- 查询操作:get、load、createQuery、createCriteria 等 获得都是持久态
- 持久态转换为瞬时态调用delete()
- 持久态转换为游离态session调用close()
- 创建对象,并设置OID为游离态(托管态)
- 游离态转换为瞬时态将OID设置为null 游离态转换为持久态调用update()或者saveOrUpdate()
- 无论对象是瞬时还有游离只要调用saveOrUpdate()都会变成持久态
public void demo01(){
User user = new User(); //瞬时态
user.setUsername("jack");
user.setPassword("1234"); //瞬时态(与oid没有关系)
Session session = factory.openSession();
session.beginTransaction();
session.save(user); //持久态
//---- 持久态就应该有持久态的行为(特性)
// user.setUsername("rose"); //持久态对象 被修改后,hibernate将自动生成update语句
// session.flush();
session.getTransaction().commit();
session.close();
System.out.println(user); //脱管态
一级缓存
- 一级缓存又称为session级别的缓存。当获得一次会话(session),hibernate在session中创建多个集合(map),用于存放操作数据(po对象),为程序优化服务,如果之后需要相应的数据,hibernate优先从session缓存中获取,如果有就使用;如果没有在再查询数据库。当session关闭时,一级缓存销毁。
- 目的:减少访问数据库的次数
public void demo03(){
//清除缓存
Session session = factory.openSession();
session.beginTransaction();
User user = (User) session.get(User.class, 1); //--select
System.out.println(user);
//清除
//session.clear();
session.evict(user);
// 一级缓存没有缓存对象,从数据库直接查询
User user2 = (User) session.get(User.class, 1); //--select
System.out.println(user2);
session.getTransaction().commit();
session.close();
}
二级缓存
Hibernate中提供了 二级缓存,一级缓存是Session级别的缓存,它属于事物范围的缓存,该缓存由Hibernate管理,程序无需干涉,二级缓存是SessionFactory级别的缓存该缓存可以配置和更改,是一种可插配的缓存框架,如果用户想使用则在主配置文件hibernate.cfg.xml配置即可,不想使用则直接移除即可。因为SessionFactory对象的生命周期和整个应用过程相对应,所以不同的session都可以访问该缓存中的数据。
Hibernate的二级缓存策略的一般过程如下
1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。
2) 把获得的所有数据对象根据ID放入到第二级缓存中。
3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。
4) 删除、更新、增加数据的时候,同时更新缓存。 Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query Cache。
二级缓存适用范围
适合放入二级缓存的数据: 可以缓解数据库的压力 很少被修改 不是很重要的数据,允许出现偶尔的并发问题
不适合放入二级缓存的数据: 经常被修改 财务数据,绝对不允许出现并发问题 与其他应用数据共享的数据
二级缓存常用的缓存插件
Hibernater 的二级缓存是一个插件,下面是几种常用的缓存插件:
l EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。
l OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。
l SwarmCache:可作为群集范围内的缓存,但不支持Hibernate的查询缓存。
l JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持
开启二级缓存需要配置什么
1.导入optional文件夹中ehcache文件夹的所有jar包
2.创建一个 ehcache.xml 的配置文件,来配置缓存信息(从etc文件夹中拷贝一份)
3.在hibernate.cfg.xml配置文件中配置二级缓存的属性
<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 二级缓存的提供类 在hibernate4.0版本以后我们都是配置这个属性来指定二级缓存的提供类-->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <!-- 二级缓存配置文件的位置 -->
<property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>
4.开启二级缓存 如果使用xml配置,需要在.hbm.xml中添加
<cache usage="read-only"/>
如果使用annotation配置,我们需要在Student这个类上加上这样一个注解 @Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 表示开启二级缓存,并使用read-only策略 二级缓存的使用策略一般有这几种:read-only、nonstrict-read-write、read-write、transactional。注意:我们通常使用二级缓存都是将其配置成 read-only ,即我们应当在那些不需要进行修改的实体类上使用二级缓存,否则如果对缓存进行读写的话,性能会变差,这样设置缓存就失去了意义
ehcache.xml配置详解
可以给每个实体类指定一个对应的缓存,如果没有匹配到该类,则使用这个默认的缓存配置
maxElementsInMemory 在内存中存放的最大对象数
eternal 是否永久保存缓存,设置成false
timeToLiveSeconds的定义是:以创建时间为基准开始计算的超时时长;
timeToIdleSeconds的定义是:在创建时间和最近访问时间中取出离现在最近的时间作为基准计算的超时时长;
如果仅设置了timeToLiveSeconds,则该对象的超时时间=创建时间+timeToLiveSeconds,假设为A;
如果没设置timeToLiveSeconds,则该对象的超时时间=max(创建时间,最近访问时间)+timeToIdleSeconds,假设为B;
如果两者都设置了,则取出A、B最少的值,即min(A,B),表示只要有一个超时成立即算超时。