0

0

详解Java的Hibernate框架中的缓存与原生SQL语句的使用

高洛峰

高洛峰

发布时间:2017-01-23 11:48:48

|

1213人浏览过

|

来源于php中文网

原创

hibernate缓存
缓存是所有关于应用程序的性能优化和它位于应用程序和数据库之间,以避免数据库访问多次,让性能关键型应用程序有更好的表现。

缓存对Hibernate很重要,它采用了多级缓存方案下文所述:

详解Java的Hibernate框架中的缓存与原生SQL语句的使用

第一级缓存:
第一级缓存是Session的缓存,是一个强制性的缓存,通过它所有的请求都必须通过。 Session对象不断自身的动力的对象,提交到数据库之前。

如果发出多个更新一个对象,Hibernate试图拖延尽可能长的时间做了更新,以减少发出的更新SQL语句的数量。如果您关闭会话,所有被缓存的对象都将丢失,要么持久,或在数据库中更新。

立即学习Java免费学习笔记(深入)”;

二级缓存:
二级缓存是可选的缓存和一级缓存,总是会征询任何试图找到一个对象的二级缓存之前。第二级缓存可以在每个类和每个集合基础上进行配置,主要负责在会话缓存的对象。

任何第三方缓存可以使用Hibernate。org.hibernate.cache.CacheProvider接口提供,必须实施提供Hibernate一个句柄缓存实现。

查询级别缓存:
Hibernate也实现了查询结果集缓存与二级缓存的紧密集成在一起。

这是一个可选功能,需要两个额外的物理缓存中保存缓存的查询结果和地区当一个表的最后更新的时间戳。这只是针对那些使用相同的参数经常运行的查询非常有用。

二级缓存:
Hibernate使用一级缓存,默认情况下,你什么都没有做使用第一级缓存。让我们直接进入可选的第二级缓存。并不是所有的类受益于缓存,这样一来就能禁用二级缓存是很重要的

Hibernate二级缓存被设置为两个步骤。首先,必须决定要使用的并发策略。在此之后,可以配置缓存过期和使用缓存提供物理缓存属性。

并发策略:
并发策略是一个中介的负责存储数据项在缓存并从缓存中检索它们。如果要启用二级缓存,将必须决定,为每个持久化类和集合,要使用的缓存并发策略。

Transactional: 使用这种策略的主要读取数据的地方,以防止过时的数据的并发事务,在更新的罕见情况下是至关重要的。

Read-write: 再次使用这种策略的主要读取数据的地方,以防止并发事务陈旧的数据是至关重要的,在更新的罕见情况。

Nonstrict-read-write: 这种策略不保证缓存与数据库之间的一致性。使用此策略,如果数据很少改变和陈旧数据的可能性很小关键是不关注。

Read-only: 并发策略适用于数据,永远不会改变。使用数据仅供参考。

如果我们要使用第二级缓存为我们的Employee类,让我们添加告诉Hibernate使用可读写的高速缓存策略Employee实例所需的映射元素。


 
 

  
   
     This class contains the employee detail. 
   
   
   
     
   
   
   
   
  

 usage="read-write" 属性告诉Hibernate使用一个可读写的并发策略定义的缓存。

缓存提供者:
考虑到会用你的缓存候选类的并发策略后,下一步就是选择一个缓存提供程序。Hibernate迫使选择一个缓存提供整个应用程序。

详解Java的Hibernate框架中的缓存与原生SQL语句的使用

在指定hibernate.cfg.xml配置文件中的缓存提供。选择EHCache作为第二级缓存提供程序:



 

  
  
   org.hibernate.dialect.MySQLDialect
  
  
   com.mysql.jdbc.Driver
  
 
  
  
   jdbc:mysql://localhost/test
  
  
   root
  
  
   root123
  
  
   org.hibernate.cache.EhCacheProvider
  
 
  
  
 

现在,需要指定缓存区域的属性。EHCache都有自己的配置文件ehcache.xml,在应用程序在CLASSPATH中。在ehcache.xml中Employee类高速缓存配置可能看起来像这样:



 

就这样,现在启用Employee类的二级缓存和Hibernate现在二级缓存,每当浏览到一个雇员或当通过标识符加载雇员。

应该分析你所有的类,并选择适当的缓存策略为每个类。有时,二级缓存可能降级的应用程序的性能。所以建议到基准应用程序第一次没有启用缓存,非常适合缓存和检查性能。如果缓存不提高系统性能再有就是在使任何类型的缓存是没有意义的。

查询级别缓存:
使用查询缓存,必须先使用 hibernate.cache.use_query_cache="true"属性配置文件中激活它。如果将此属性设置为true,让Hibernate的在内存中创建所需的高速缓存来保存查询和标识符集。

接下来,使用查询缓存,可以使用Query类的setCacheable(Boolean)方法。例如:

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();

Hibernate也支持通过一个缓存区域的概念非常细粒度的缓存支持。缓存区是这是给定一个名称缓存的一部分。

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();

魔珐星云
魔珐星云

无需昂贵GPU,一键解锁超写实/二次元等多风格3D数字人,跨端适配千万级并发的具身智能平台。

下载

此代码使用方法告诉Hibernate来存储和查找在缓存中的员工方面的查询。


Hibernate原生SQL
可以使用原生SQL来表达数据库查询,如果想利用数据库特有的功能,如查询提示或者Oracle中的CONNECT关键字。 Hibernate3.x允许使用手写SQL语句,包括存储过程,所有的创建,更新,删除和load操作。

应用程序将从会话创建一个原生SQL查询(Session接口上)createSQLQuery()方法:

public SQLQuery createSQLQuery(String sqlString) throws HibernateException
当传递一个包含SQL查询到createSQLQuery()方法,可以将SQL结果与任何现有的Hibernate实体,联接,或者一个标量结果使用addEntity()方法,addJoin(),和addScalar()方法关联的字符串。

标量查询:
最基本的SQL查询是从一个或多个表中得到标量(数值)的列表。以下是语法使用原生SQL标量的值:

String sql = "SELECT first_name, salary FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List results = query.list();

实体的查询:
上面的查询都是返回标量值,也就是从resultset中返回的“裸”数据。以下是语法通过addEntity()方法来从原生SQL查询获得实体对象作为一个整体。

String sql = "SELECT * FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
List results = query.list();

命名SQL查询:
以下是语法通过addEntity()方法来从原生SQL查询获得实体对象和使用命名SQL查询。

String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
query.setParameter("employee_id", 10);
List results = query.list();

Native SQL 例子:
考虑下面的POJO类:

public class Employee {
  private int id;
  private String firstName;
  private String lastName; 
  private int salary;
 
  public Employee() {}
  public Employee(String fname, String lname, int salary) {
   this.firstName = fname;
   this.lastName = lname;
   this.salary = salary;
  }
  public int getId() {
   return id;
  }
  public void setId( int id ) {
   this.id = id;
  }
  public String getFirstName() {
   return firstName;
  }
  public void setFirstName( String first_name ) {
   this.firstName = first_name;
  }
  public String getLastName() {
   return lastName;
  }
  public void setLastName( String last_name ) {
   this.lastName = last_name;
  }
  public int getSalary() {
   return salary;
  }
  public void setSalary( int salary ) {
   this.salary = salary;
  }
}

让我们创建下面的EMPLOYEE表来存储Employee对象:

create table EMPLOYEE (
  id INT NOT NULL auto_increment,
  first_name VARCHAR(20) default NULL,
  last_name VARCHAR(20) default NULL,
  salary   INT default NULL,
  PRIMARY KEY (id)
);

以下将被映射文件。



 

  
   
     This class contains the employee detail.
   
   
     
   
   
   
   
  

   

最后,我们将创建应用程序类的main()方法来运行,我们将使用原生SQL查询的应用程序:

import java.util.*;
  
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.SQLQuery;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.cfg.Configuration;
 
public class ManageEmployee {
  private static SessionFactory factory;
  public static void main(String[] args) {
   try{
     factory = new Configuration().configure().buildSessionFactory();
   }catch (Throwable ex) {
     System.err.println("Failed to create sessionFactory object." + ex);
     throw new ExceptionInInitializerError(ex);
   }
   ManageEmployee ME = new ManageEmployee();
 
   /* Add few employee records in database */
   Integer empID1 = ME.addEmployee("Zara", "Ali", 2000);
   Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
   Integer empID3 = ME.addEmployee("John", "Paul", 5000);
   Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000);
 
   /* List down employees and their salary using Scalar Query */
   ME.listEmployeesScalar();
 
   /* List down complete employees information using Entity Query */
   ME.listEmployeesEntity();
  }
  /* Method to CREATE an employee in the database */
  public Integer addEmployee(String fname, String lname, int salary){
   Session session = factory.openSession();
   Transaction tx = null;
   Integer employeeID = null;
   try{
     tx = session.beginTransaction();
     Employee employee = new Employee(fname, lname, salary);
     employeeID = (Integer) session.save(employee);
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace();
   }finally {
     session.close();
   }
   return employeeID;
  }
 
  /* Method to READ all the employees using Scalar Query */
  public void listEmployeesScalar( ){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     String sql = "SELECT first_name, salary FROM EMPLOYEE";
     SQLQuery query = session.createSQLQuery(sql);
     query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
     List data = query.list();
 
     for(Object object : data)
     {
      Map row = (Map)object;
      System.out.print("First Name: " + row.get("first_name"));
      System.out.println(", Salary: " + row.get("salary"));
     }
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace();
   }finally {
     session.close();
   }
  }
 
  /* Method to READ all the employees using Entity Query */
  public void listEmployeesEntity( ){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     String sql = "SELECT * FROM EMPLOYEE";
     SQLQuery query = session.createSQLQuery(sql);
     query.addEntity(Employee.class);
     List employees = query.list();
 
     for (Iterator iterator =
              employees.iterator(); iterator.hasNext();){
      Employee employee = (Employee) iterator.next();
      System.out.print("First Name: " + employee.getFirstName());
      System.out.print(" Last Name: " + employee.getLastName());
      System.out.println(" Salary: " + employee.getSalary());
     }
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace();
   }finally {
     session.close();
   }
  }
}

编译和执行:
下面是步骤来编译并运行上述应用程序。请确保在进行的编译和执行之前,适当地设置PATH和CLASSPATH。

执行ManageEmployee二进制文件来运行程序。

会得到以下结果,并记录将在EMPLOYEE表中创建。

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
 
First Name: Zara, Salary: 2000
First Name: Daisy, Salary: 5000
First Name: John, Salary: 5000
First Name: Mohd, Salary: 3000
First Name: Zara Last Name: Ali Salary: 2000
First Name: Daisy Last Name: Das Salary: 5000
First Name: John Last Name: Paul Salary: 5000
First Name: Mohd Last Name: Yasee Salary: 3000

如果检查EMPLOYEE表,它应该记录下已:

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 26 | Zara    | Ali    |  2000 |
| 27 | Daisy   | Das    |  5000 |
| 28 | John    | Paul   |  5000 |
| 29 | Mohd    | Yasee   |  3000 |
+----+------------+-----------+--------+
4 rows in set (0.00 sec)

更多详解Java的Hibernate框架中的缓存与原生SQL语句的使用相关文章请关注PHP中文网!

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

39

2026.02.06

java多线程方法汇总
java多线程方法汇总

本专题整合了java多线程面试题、实现函数、执行并发相关内容,阅读专题下面的文章了解更多详细内容。

17

2026.02.06

1688阿里巴巴货源平台入口与批发采购指南
1688阿里巴巴货源平台入口与批发采购指南

本专题整理了1688阿里巴巴批发进货平台的最新入口地址与在线采购指南,帮助用户快速找到官方网站入口,了解如何进行批发采购、货源选择以及厂家直销等功能,提升采购效率与平台使用体验。

289

2026.02.06

快手网页版入口与电脑端使用指南 快手官方短视频观看入口
快手网页版入口与电脑端使用指南 快手官方短视频观看入口

本专题汇总了快手网页版的最新入口地址和电脑版使用方法,详细提供快手官网直接访问链接、网页端操作教程,以及如何无需下载安装直接观看短视频的方式,帮助用户轻松浏览和观看快手短视频内容。

150

2026.02.06

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

11

2026.02.06

Python 微服务架构与 FastAPI 框架
Python 微服务架构与 FastAPI 框架

本专题系统讲解 Python 微服务架构设计与 FastAPI 框架应用,涵盖 FastAPI 的快速开发、路由与依赖注入、数据模型验证、API 文档自动生成、OAuth2 与 JWT 身份验证、异步支持、部署与扩展等。通过实际案例,帮助学习者掌握 使用 FastAPI 构建高效、可扩展的微服务应用,提高服务响应速度与系统可维护性。

7

2026.02.06

JavaScript 异步编程与事件驱动架构
JavaScript 异步编程与事件驱动架构

本专题深入讲解 JavaScript 异步编程与事件驱动架构,涵盖 Promise、async/await、事件循环机制、回调函数、任务队列与微任务队列、以及如何设计高效的异步应用架构。通过多个实际示例,帮助开发者掌握 如何处理复杂异步操作,并利用事件驱动设计模式构建高效、响应式应用。

11

2026.02.06

java连接字符串方法汇总
java连接字符串方法汇总

本专题整合了java连接字符串教程合集,阅读专题下面的文章了解更多详细操作。

47

2026.02.05

java中fail含义
java中fail含义

本专题整合了java中fail的含义、作用相关内容,阅读专题下面的文章了解更多详细内容。

29

2026.02.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.3万人学习

C# 教程
C# 教程

共94课时 | 8.9万人学习

Java 教程
Java 教程

共578课时 | 60.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号