`

hibernate05:二级缓存、一级与二级的差别、主键生成策略

 
阅读更多

第一.概念

Shift+第一个+最后一个=全部选中jar包
1.数据库和tomcat服务器不在一台电脑上,一级缓存是保存在服务器的内存中,二级缓存保存在服务器的硬盘上(因此我们可以设置溢出时保存到哪个硬盘),二级缓存也是在tomcat服务器上的,因此减少了与数据库的交互次数(因为保存到服务器的话不用跟其他的电脑进行交互)。
2.hibernate的一级缓存是session级别的缓存。sessionFactory级别的缓存是二级缓存。
3.二级缓存要指定hibernate的二级缓存插件(插件是个现成的程序,需要我们指定用这个插件),需要开启
4.hibernate主配置文件中的设置都是给某个类进行赋值,是个sessionFactory类(session工厂)中的属性赋值。sessionFactory是个接口,实现类是sessionFactoryimpl
资源文件Properties 继承了hashtable,因此Properties 是个键值对。
来自JDK1.6说明文档:Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

5.在properties文件中#表示注释
6,使用二级缓存的步骤:
  ---1.开启二级缓存
 ---2.指定缓存插件(功能是把内容写到磁盘中,当开启二级缓存之后就该想到我们将来要把内容存到哪里)
  --3.写配置文件说明二级缓存的大小,在src下配置缓存文件
  --4.指定需要缓存的对象和缓存策略
7.statics是对二级缓存进行统计,输出来的内容create(可瑞的)是该对象的属性。在主配置文件中配置。
他是查看二级缓存或查询缓存区域的内容,但是如果想查看二级缓存,需要在主配置文件中进行配置。查看二级缓存是SessionFactory类中的的方法Statistics ss=HibernateSessionFactory.getSessionFactory().getStatistics();
其实不难理解为什么是SessionFactory类中的方法,因为SessionFactory表示的是二级缓存。而session表示一级缓存。

8.适合放入二级缓存中的数据:1.不经常做修改的数据,2.安全性不高的数据。
9.先查询已经缓存,一级缓存中如果没有在查询二级缓存,如果二级缓存中也没有,就查询数据库。
10.session(一级)和sesionFactroy(二级)的线程安全问题
 session是线程不安全的:ThreadLocal是给每个来的线程都给他一个副本,用这种方式来解决多线程问题。sessionFactroy是线程安全的。
注意:在hibernate主配置文件中,二级缓存的配置要放到映射文件配置的前面

11.session和sessionFactory都有evict方法,该方法的参数是个对象或者类,表示让该对象与一级缓存或者二级缓存断开联系:sessionFactory.evict(Cat.class, catId); sessionFactory.evict(Cat.class);
/**
关于二级缓存:二级缓存就是给大家共享的,每个线程都能够使用,因此就出现了多线程并发的现象。
      第一步(1):在hibernate主配置文件中写:
               <!--设置二级缓存  -->
  <property name="hibernate.cache.provider_class">
   org.hibernate.cache.EhCacheProvider
  </property>
  <!--默认是使用二级缓存的,但是可以设置关闭  -->  
  <property name="hibernate.cache.use_second_level_cache">
     false
  </property>
  <!-- 使用查询缓存 -->
  <property name="hibernate.cache.use_query_cache">true</property>
     第一步(2):在映射文件中写二级缓存的并发策略。usage表示并发策略。
 <cache usage="read-write"/>
     第二步:指定二级缓存的插件(有好多种插件都能实现二级缓存,其实就是把某个xml文件放到src目录下(放在src下就会随着项目的启动而启动二级缓存)。现在要指定插件,在老师给的hibernate-3.2下的ect目录下)
     第三步:配置上面的插件(可以只配置缓存的大小)
----------------------------------
注意:现在我们只导入了hibernate的jar包,在配置好二级缓存之后运行的时候报错Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory。
这是找不到这个jar包(也就是说明二级缓存要使用这个jar包),因此我们可以找一个这样的jar包放到项目中,也可以直接把struts框架的jar包生成,因为struts2框架的jar包就有这个jar包
并发策略有好多种,看张老师的,可是我们常用的只有两种只读模式和读写模式,当我们设置读写模式的时候就不能设置事务的隔离级别了,因为这两个是互相矛盾的。
**/

11.主键生成策略:
increment(k瑞特门):自动增长因用于mysql,
identity自增用于mysql,server,db2,
sequence是oracle中的自增
native(内t我):根据数据库自动匹配(相当于综合各种数据库),由数据库底层自己决定。
assigned:程序员自己指定
uuid:是个算法

12.hql的多表关联(多表关联有三种,一种是hql的多表关联,一个createCriteria(也就是QBC查询),一个是本地sql查询)
inner默认是内连接,inner join。左是left join
   内左外右外连接查询:查询结果是个object类型的数组,因为这个查询结果中包含两个或者两个以上的表(类),因此不能是具体类型,只能是object类型。因为包含多个表,表中又有属性,因此每个表都是一个数组。
   迫切查询:返回值是个对象

13.createCriteria多表关联
  两个参数,第一个是类名,第二个是别名,单词是alias
  两个参数,第一个参数表示地址,第二个参数是数据类型(在Criteria里面的常量)

14,hibernate的源码在hibernate-3.2这个老师给的文件中的src中,如果找二级缓存的资源文件在这个文件夹中的ect中。

一级缓存session的声明周期是与数据库的一次交互过程,当我们把session放到action层的时候,它的声明周期是一次请求和响应的过程(可能多次与数据库交互)
而二级缓存是:不但在一级缓存的map结构中存放(),还在二级缓存中存放(在二级缓存存放的内容是共享的)。
一级缓存的作用域相当于是hibernate主配置文件中的map标签里,而二级缓存的作用域相当于是整个hibernate主配置文件。
------------------
书17章:三种检索(查询)方式
1.hql语句检索:session.createQuery(hql);
2.QBC检索:session.createCriteria(XXX.class)
3.本地SQL检索:session.createSQLQuery(sql)
 

第二:代码

1、hibernate主配置文件

<?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">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>
 <!-- 注意:hibernatefactory里面配置的所有标签其实就是hibernatefactory接口中的属性,该接口的实现类是hibernatefactoryImpl,下面的所有配置 都是该实现类中的属性。 -->
<session-factory>
 <property name="dialect">
  org.hibernate.dialect.Oracle9Dialect
 </property>
 <property name="connection.url">
  jdbc:oracle:thin:@localhost:1521:ORCL
 </property>
 <property name="connection.username">chu1</property>
 <property name="connection.password">1234</property>
 <property name="connection.driver_class">
  oracle.jdbc.OracleDriver
 </property>
 <property name="myeclipse.connection.profile">chu</property>
 <property name="format_sql">true</property>
 <property name="show_sql">true</property>
 <!--设置二级缓存,指定缓存插件,是个类,是个jar包里面的类  -->
 <property name="hibernate.cache.provider_class">
  org.hibernate.cache.EhCacheProvider
 </property>
 <!--默认是使用二级缓存的,但是可以设置关闭。打开二级缓存  -->
 <property name="hibernate.cache.use_second_level_cache">
  true
 </property>
 <!-- 使用查询缓存,查询缓存有利于提高查询速度,也是个jar包里的类 -->
 <property name="hibernate.cache.use_query_cache">true</property>
 <!--表示允许查看二级缓存里面放的数据-->
 <property name="generate_statistics">true</property>

 <mapping resource="com/model/pojo/Student6.hbm.xml" />

</session-factory>

</hibernate-configuration>

 

 

2.basedao公共类

package com.comm;

import java.io.Serializable;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class BaseDao
{
 public static SessionFactory sf;
 static
 {
  Configuration cfg=new Configuration().configure("/hibernate.cfg.xml");
  sf = cfg.buildSessionFactory();
  System.out.println(sf);
 }

 public Session getSession()
 {
  return sf.openSession();
 }
 
 public Serializable save(Object obj)
 { 
  Transaction  tr=null;
  Session session=null;
  Serializable ser=null;
  try
  {
   session = this.getSession();
   
   tr= session.beginTransaction();
   
   ser=session.save(obj);
   
   tr.commit();
   
   
  }
  catch(Exception ex)
  {
   ex.printStackTrace();
  }
  finally
  {
   session.close();
  }
  return ser;
  
 }
 
 public static void main(String[] args) {
  new BaseDao();
 }
}

 

3.dao层

package com.model.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.stat.Statistics;

import com.comm.BaseDao;
import com.comm.HibernateSessionFactory;
import com.model.pojo.Student6;

public class StudentDao extends BaseDao{
 //一级缓存。此时不开启二级缓存。在主配置文件中设置成false
 public void search(){
  Session session=super.getSession();
  Student6 stu=(Student6) session.get(Student6.class, 168);
  System.out.println(stu.getSname()+"\t"+stu.getSsex()); 
  //session.evict(stu);//将当前对象与session断开
  //session.clear();//清空session
  session.close();//关闭session
  Session session2=super.getSession();
  System.out.println("session是打开的?"+session.isOpen());
  //System.out.println("当前session"+session.hashCode());
  System.out.println(stu.getSname()+"\t"+stu.getSsex());//无论什么操作,这里都会输出值,因为这里跟缓存无关,由于限制存在一个完整的stu对象,所以理所当然的能够输出他的属性值。
    
 }
 //自己的session关闭之后其他session来访问相同的内容(id相同的学生),由于第一个session把查询结果放在了二级缓存中了,因此第二个session查询相同的学生的时候不会访问数据库而是直接去二级缓存中取,因此控制台输出一条sql语句
 public void search2(){
  Session session=HibernateSessionFactory.getSession();
  Student6 stu=(Student6) session.get(Student6.class, 168);
  System.out.println(stu.getSname()+"\t"+stu.getSsex());
  //session.clear();//清空一级缓存
  session.close();
  Session session2=HibernateSessionFactory.getSession();
  Student6 stu2=(Student6) session2.get(Student6.class, 168);//会查看二级缓存中有没有,当我们开启二级缓存的时候,使用二级缓存,因此不会再输出select语句了
  System.out.println(stu2.getSname()+"\t"+stu2.getSsex());//
  Statistics ss=HibernateSessionFactory.getSessionFactory().getStatistics();//getSessionFactory()是获得sesionFactory也就是获得二级缓存,getStatistics是获得二级缓存中的统计信息
  System.out.println(ss);
 }
 
 
 public static void main(String[] args) {
  StudentDao sdao = new StudentDao();
  //sdao.search();
  sdao.search2();
  //sdao.search3();
 }

}

 

 

第三:多表连接查询,对象查询的代码

1.员工表的映射文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping package="com.model.pojo">
    <class name="Emp" table="HIB_EMP" schema="CHU1">
        <id name="eid" type="int">
            <column name="EID" precision="10" scale="0" />
            <generator class="assigned" />
        </id>
        <many-to-one name="dept" class="Dept" fetch="select">
            <column name="DID" precision="10" scale="0" />
        </many-to-one>
        <property name="ename" type="string">
            <column name="ENAME" length="40" />
        </property>
        <property name="job" type="string">
            <column name="JOB" length="40" />
        </property>
     
    </class>
</hibernate-mapping>

 

2.部门表的映射文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping package="com.model.pojo">
    <class name="Dept" table="HIB_DEPT" schema="CHU1">
        <id name="did" type="int">
            <column name="DID" precision="10" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="dname" type="string">
            <column name="DNAME" length="40" />
        </property>
        <set name="emps" inverse="true">
            <key>
                <column name="DID" precision="10" scale="0" />
            </key>
            <one-to-many class="Emp" />
        </set>
    </class>
</hibernate-mapping>

3.连接查询和本地查询

package com.model.dao;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;

import com.comm.HibernateSessionFactory;
import com.model.pojo.Dept;
import com.model.pojo.Emp;

public class DeptDao {

 public static void main(String[] args) {
  DeptDao ddao=new DeptDao();
  //ddao.selDept();
  //ddao.selDept1();
  //ddao.selDept2();
  ddao.selDept3();
 }
 //通过这个方法我们发现内连接,左连接、右连接的查询结果是个object类型的数组
 public void selDept(){
  Session session=HibernateSessionFactory.getSession();
  String hql="from Dept as d inner join d.emps";
  Query query = session.createQuery(hql);
  List list = query.list();
  for(int x=0;x<list.size();x++){
   System.out.print(list.get(x)+"    ");//这个得到的是个数组,也就是说集合里面放的是数组。由此得出结论
   System.out.println();
  }
  
 }
 //通过这个方法我们知道,数组中的每个元素都表示多表关联中的每个表,也就是说有几个表数组中就会有几个元素
 public void selDept1(){
  Session session=HibernateSessionFactory.getSession();
  String hql="from Dept as d inner join d.emps";
  Query query = session.createQuery(hql);
  List<Object[]> list = query.list();//首先查询结果有很多,是个list集合(query.list的返回值就是个list)。每个查询结果又是个数组,数组中的每个元素表示一个表(由于内连接,左右连接都是两个或者两个以上的表在参与)
  for(Object[] d:list){
   System.out.println(d[0].getClass().getName()+"\t"+d[1].getClass().getName());
  }  
 }
 //迫切左外连接。集合的返回值得到的是对象类型的list集合
 public void selDept2(){
  Session session=HibernateSessionFactory.getSession();
  String hql="from Dept as d left join  fetch d.emps";
  Query query = session.createQuery(hql);
  List<Dept> list=query.list();
  for(Dept d:list){
   System.out.println(d.getDname());
   Set<Emp> set=d.getEmps();
   Iterator<Emp> it = set.iterator();
   while(it.hasNext()){
    System.out.println(it.next().getEname());
   }
  }
  
 }
 //本地sql查询
 public void selDept3(){
  Session session=HibernateSessionFactory.getSession();
  String sql="select * from dept";//创建sql语句
  Query query = session.createSQLQuery(sql).addEntity(Dept.class);//addEntity是把sql变成hql,把表名变成类名
  System.out.println(query);
  int a=query.executeUpdate();
  System.out.println(a);
  
  
 }
}

 

4.对象查询

package com.model.dao;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import com.comm.HibernateSessionFactory;
import com.model.pojo.Emp;

public class EmpDao {
 public static void main(String[] args) {
  EmpDao edao=new EmpDao();
  edao.selEmp();
  
 }
 //QBC查询,也叫对象查询
 public void selEmp(){
  Session session=HibernateSessionFactory.getSession();
  //第一个参数是个路径,第二个参数是别名(String associationPath, String alias)
  Criteria c = session.createCriteria(Emp.class, "e");//创建QBC查询语句,并给则个对象起个别名e
  //第一个参数是路径,第二个参数是连接类型(例如左外连接,内连接等)(String associationPath, int joinType)
  //连接类型中的1是Criteria接口的实现类CriteriaSpecification(查看源代码)中的一个常量的值,
  c.createCriteria("e.dept",1);//左连接
  c.add(Restrictions.eq("e.ename","喜洋洋"));
  List<Emp> elist = c.list();
  for(Emp e:elist){
   System.out.println(e.getEname());
   System.out.println(e.getDept().getDname());
  }
 }
 
 

}

 

 

分享到:
评论

相关推荐

    spring hibernate 事务管理学习笔记(二)

    在本篇“Spring Hibernate 事务管理学习笔记(二)”中,我们将深入探讨Spring框架与Hibernate集成时如何实现高效、安全的事务管理。这是一篇关于源码分析和技术工具使用的文章,适合对Java开发和数据库操作有基础...

    详解Java的Hibernate框架中的注解与缓存

    例如,`@Entity`注解标记一个类为实体,`@Table`注解指定了实体对应的数据库表名,`@Id`注解标识实体的主键字段,`@GeneratedValue`注解指示主键生成策略,而`@Column`注解则用于指定字段与表列的对应关系。...

    hibernate-release-5.2.3.Final

    Hibernate支持二级缓存,包括一级缓存(Session级别的缓存)和二级缓存(SessionFactory级别的缓存)。如使用EhCache作为二级缓存,可以显著提升系统性能。 9. 异构数据库支持: Hibernate具有强大的数据库无关性...

    精通 Hibernate:Java 对象持久化技术详解(第2版

    6.缓存机制:理解Hibernate的缓存层次,包括一级缓存(Session级别的缓存)和二级缓存(SessionFactory级别的缓存),以及第三方缓存集成,如EhCache和Redis。 7. 性能优化:学习如何提升Hibernate应用的性能,包括...

    hibernate 中文文档 and _annotation.chm

    - @Id:标识类中的主键字段,可以配合@GeneratedValue指定主键生成策略。 - @GeneratedValue:定义主键的自增策略,如IDENTITY(数据库自动增长)、SEQUENCE(序列)等。 - @Column:定义属性对应表中的列,可以...

    hibernate难点重点笔记

    本文将针对Hibernate中的几个重要概念进行详细讲解,包括主键生成策略、get()与load()的区别以及二级缓存的使用。 首先,探讨的是Hibernate中的主键生成策略。在Hibernate中,主键的生成主要有三种方式:uuid、...

    精通hibernate源码ch2

    - @Id:定义主键字段,通常与@IdGenerator配合使用定义主键生成策略。 4. Hibernate的Session操作: - save()和saveOrUpdate():将对象持久化到数据库,如果对象尚未存在,会创建新记录。 - update():更新已...

    hibernate第一天笔记

    总的来说,Hibernate第一天的学习涵盖了基本的环境配置、对象关系映射、主键生成策略、`SessionFactory`和`Session`的使用,以及事务管理和缓存机制。理解并掌握这些基础概念,是进一步深入学习Hibernate和进行实际...

    Hibernate常见面试题汇总

    可能会返回代理对象,并优先检查一级和二级缓存。 Hibernate的加载过程包括: - **一级缓存检查**:Session内部的缓存管理。 - **二级缓存检查**:SessionFactory级别的缓存,多个Session共享。 - **数据库查询...

    hibernate实战第二版.pdf

    2. **映射配置**:详细讲解了XML配置文件(hibernate.cfg.xml和.hbm.xml)和注解方式,如何定义实体类和数据库表之间的映射关系,包括主键生成策略、属性类型映射、关联映射(一对一、一对多、多对多)等。...

    Hibernate高级教程

    3. **对象关系映射(ORM)**:讲解Hibernate的核心——ORM技术,如何通过注解或XML配置文件将Java类与数据库表进行映射,包括实体类的定义、主键生成策略、属性映射等。 4. **Session和Transaction**:深入理解...

    数据库与Hibernate教案

    -缓存机制:理解一级缓存和二级缓存,以及查询缓存的工作原理。 3. **关联映射**: - 一对一、一对多、多对一、多对多关联映射的配置和实现,包括集合类型如List、Set、Map的使用。 -懒加载和立即加载策略,以及...

    Hibernate开发指南

    6.缓存机制:讲解Hibernate的缓存策略,包括一级缓存和二级缓存,以及第三方缓存解决方案如 EhCache 和 Infinispan 的集成。 7.性能优化:分享提高Hibernate应用性能的技巧,如延迟加载、批处理、预加载等。 通过...

    hibernate-release-5.2.10

    Hibernate提供了一级缓存(Session级别)和二级缓存(SessionFactory级别)。一级缓存默认开启,二级缓存可配置插件如EhCache实现,提高数据访问效率。 八、延迟加载(Lazy Loading) Hibernate支持懒加载策略,...

    hibernate5.2.7-src源码

    4. 缓存机制:Hibernate包含一级缓存(Session级缓存)和二级缓存(SessionFactory级缓存),以及查询缓存,有效提高数据访问速度。 四、核心类详解 1. EntityPersister:负责实体的持久化操作,包括保存、更新、...

    Hibernate Soruce Code 源代码

    4. 映射文件(.hbm.xml或注解):定义对象和数据库表之间的映射关系,包括字段对应、主键生成策略、关联关系等。 5. Query与Criteria API:提供查询对象和数据的方法,包括HQL(Hibernate Query Language)和JPQL...

    hibernate数据包

    - 缓存机制:提供了第一级缓存和第二级缓存,提高性能。 - 支持多种数据库:通过配置文件可以轻松切换不同的数据库平台。 - 自动SQL生成:根据对象模型自动生成SQL,减少手动编写SQL的工作量。 5. 使用流程: -...

    Hibernate开发所需的jar包

    - `@Table`注解指定表名,`@Id`定义主键,`@GeneratedValue`管理主键生成策略。 - `@Column`定义字段与列的映射,`@ManyToOne`, `@OneToOne`, `@OneToMany`, `@ManyToMany`处理关联关系。 4. Session与...

    hibernate学习文档

    Hibernate 是一个强大的 Java 对象关系映射(ORM)框架,它极大地简化了数据库操作,让...同时,了解如何配置和管理二级缓存,以及如何根据不同的数据库环境选择合适的主键生成策略,也是提高应用程序性能的关键。

    hibernate课程笔记.doc

    - **映射文件**(`.hbm.xml`):定义对象与表之间的映射规则,如字段对应、主键生成策略等。 ### 6. 常见操作 - **查询**:使用Session的`load()`或`get()`方法获取对象,`createCriteria()`或`createQuery()`构建...

Global site tag (gtag.js) - Google Analytics