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基础知识整理的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate基础知识整理

Hibernate基础知识整理

Hibernate知识点整理

具有运行时 pojos 的带有 Hibernate 的 OSGi 片段包

IOS开发-OC学习-常用功能代码片段整理

VS2015 代码片段整理