Hibernate基础知识整理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate基础知识整理相关的知识,希望对你有一定的参考价值。
继承映射
Employee(id,name,age);
Skiller extends Employee {skill};
Seller extends Employee{sell};
一:一张表实现继承映射
create table Employee(id int primary key,name varchar(20),age date,skill varchar(20),sell varchar(20));
映射文件Employee.hbm.xml相关配置:
<class name="Employee">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="age"/>
</class>
添加<discriminator column="type" type="int"> ——鉴别器,缺省类型是字符串类型,挨着id写 ,并用discriminator-value=""进行区分,如下:
<class name="Employee" discriminator-value="0"> <id name="id"> <generator class="native"/> </id> <discriminator column="type" type="int"> <property name="name"/> <property name="age"/> <subclass name="Skiller" discriminator-value="1"> <property name="skill"/> </subclass> <subclass name="Seller" discriminator-value="2"> <property name="sell"/> </subclass> </class>
这种配置效率较高,但是再增加子类,就必须再增加字段,并且不能设置多出来的字段为不为空;
二:每一个子类一张表,通过外键关联
Employee(id,name,age);
Skiller extends Employee {skill};
Seller extends Employee{sell};
表:
create table employee(id int primary key,name varchar(20),age date);
create table skiller(employee_id int primary key,skill varchar(20),foreign key (employee_id) references employee(id));
create table seller(employee_id int primary key,sell varchar(20),foreign key (employee_id) references employee(id));
映射Employee.hbm.xml文件相关配置:
<class name="Employee">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="age"/>
</class>
添加
<joined-subclass name="Skiller" table="skiller"><!-- join表示数据库表中使用连接与子类关联 --> <key column="emp_id"/><!-- 连接使用的外键列 --> <property name="skill"/> </joined-subclass> 如下:
<class name="Employee"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <property name="age"/> <joined-subclass name="Skiller" table="skiller"> <key column="emp_id"> <property name="skill"/> </joined-subclass> <joined-subclass name="Seller" table="seller"> <key column="emp_id"> <property name="sell"/> </joined-subclass> </class>
表结构合理,子类和主类差距比较大的时候使用。
多态方式查询的话关联表过多效率低。不使用多态查询的话就比较优秀
每个子类映射成一张表有如下步骤:
父类用普通的<class>标签定义即可
父类不再需要定义discriminator字段
子类用<joined-subclass>标签定义,在定义joined-subclass的时候,需要注意如下几点:
Joined-subclass标签的name属性是子类的全路径名
Joined-subclass标签需要包含一个key标签,这个标签指定了子类和父类之间是通过哪个字段来关联的。
如:<key column=”PARENT_KEY_ID”/>,这里的column,实际上就是父类的主键对应的映射字段名称。
Joined-subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),
也可以与class标签平行。 当Joined-subclass标签的定义与class标签平行的时候,需要在Joined-subclass
标签中,添加extends属性,里面的值是父类的全路径名称。子类的其它属性,像普通类一样,定义在joined-subclass标签的内部。
三:鉴别器和内连接相关联
Employee(id,name,age);
Skiller extends Employee {skill};
Seller extends Employee{sell};
表:
create table employee(id int primary key,name varchar(20),age date,skill varchar(20));
create table seller(employee_id int primary key,sell varchar(20),foreign key (employee_id) references employee(id));
适用情况:雇员中销售的字段比较多但是技术的字段比较少
映射文件Employee.hbm.xml相关配置:
<class name="Employee">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="age"/>
</class>
添加鉴别器和join如下:
<class name="Employee" discriminator-value="0"> <!-- 鉴别属性值为0表示为普通雇员,注意:鉴别器的值如果不给的话,默认认为是类名的全名称 --> <id name="id" > <generator class="native"/> </id> <discriminator column="type" type="int"/> <!-- 鉴别器,缺省类型是字符串类型 ,鉴别器的位置放置在property前面--> <property name="name"/> <subclass name="Skiller" discriminator-value="1"> <property name="skill"/> </subclass> <subclass name="Sales" discriminator-value="2"> <join table="sales"> <key column="emp_id"/> <property name="sell"/> </join> </subclass> </class>
四:每一个类一张表,且每一个表中都具有完整信息,如果父类不是抽象的,也会有父类表
<class name="Employee"> <id name="id" > <generator class="hilo"/> </id> <property name="name"/> <union-subclass name="Skiller" table="skiller"> <!-- union表示结合的意思 --> <property name="skill"/> </union-subclass> <union-subclass name="Sales" table="sales"> <!-- union表示结合的意思 --> <property name="sell"/> </union-subclass> </class>
注意:父类和子类表的id是不能重复的,所以我们的主键生成策略不能再时native或者identity这种自增长了。
五:懒加载
懒加载就是返回的其实是一个代理对象,该代理对象是你的domain对象的一个子类。在你使用到该对象的时候,hibernate才进行数据库的查询
懒加载的对象在session关闭之后调用该属性会报错。no Session,无法访问数据库,解决方法:
1、在session未关闭之前就调用一下该对象的属性,使得hibernate访问数据库,将代理对象中的对应值填充好。
2、使用Hibernate.initialize(Object)方法实例化懒加载的对象,这样他就会查询数据库将该对象持久化。
one-to-one(元素)懒加载
必须同时满足下面三个条件:
(主表不能有constrained=true,所以主表没有懒加载)
1、lazy属性不等于false
2、constraint=true。有外键关联
3、fetch=select 抓取方式为select
多对一、一对多、多对多进行懒加载的要求:
lazy属性不能为false,
fetch为select
六:hibernate中的缓存
Hibernate的缓存分为一级缓存和二级缓存;
一级缓存(session级别的缓存):hibernate默认缓存;非线程安全
save、update、saveOrUpdate、load、get、list、iterate、lock这些方法都会将对象存入session一级缓存中;
一级缓存不能控制缓存的数量,所以请注意大批量操作数据时可能造成内存溢出,可以用evict,clear方法清除缓存中的指定对象和清空缓存。
二级缓存:可插拔的缓存,SessionFactory级别,线程安全
配置缓存插件的步骤:
1、hibernate中开启二级缓存。
在hibernate.cfg.xml中配置<property name="cache.use_second_level_cache">true</property>。这个属性在缺省状态下为true,也就是默认hibernate是打开二级缓存的
2、指定二级缓存插件的提供者。这里我使用的是OSCache
<property name="cache.provider_class">org.hibernate.cache.OSCacheProvider</property>
使用该缓存插件的时候注意你有没有导入该缓存包
src下面加入一个oscache.properties文件,然后在该文件中配置了os缓存的一些信息;
3.加入你需要对user类的对象进行缓存,当然缓存的额是持久化对象。可以在hibernate.cfg.xml中配置:
<class-cache usage="read-only" class="cn.itcast.domain.User"/>
也可以在bean的映射文件中配置,比如:
<class name="User">
<cache usage="read-only"/>
其中usage属性是表示缓存的级别:
read-only则表示缓存的东西不会发生改变,比如缓存省市这种东西的时候就可以使用这个级别的缓存。如果缓存的对象发生了改变就会报错
read-write表示允许对缓存的对象进行读写操作,而且具有很好的并发性,缓存的内容基本不会出现问题
nonstrict-read-write表示允许对缓存的对象进行读写操作,并发要求不高,可能出现一些错误数据。在你允许一些缓存问题的情况下使用,比如评论。
查看一些hibernate的状态:
可以在配置文件中打开统计信息,然后借助统计信息,得到你需要的信息。
<property name="hibernate.generate_statistics">true</property>
hibernate进行数据的查询,首先在一级缓存查找,然后如果没有在二级缓存查找,如果还没有再往数据库查找
将信息放入二级缓存的方法:
save、update、saveOrUpdate、list、iterator、get、load、以及Query、Critria都会填充二级缓存,查询数据时session的iterator、get、load可以从缓存中读取数据
注意:session中的save方法不适合native生成方式的主键,也就是说native生成方式的主键使用save方法可能不会存入缓存
Query、Criteria(查询缓存)由于命中率低,所以hibernate缺省是关闭修改hibernate.cfg.xml中的property:
<property name="cache.use_query_cache">true</property>才能打开查询缓存
并且query和Criteria存储结果入二级缓存中需要使用query.setCacheable(true),Criteria.setCacheable(true)结果才能存入二级缓存
SessionFactory中使用evit()或者evitXXX()清除缓存内容
统计信息打开generate_statics用sessionFactory.getStatics()获取统计信息
以上是关于Hibernate基础知识整理的主要内容,如果未能解决你的问题,请参考以下文章