Hibernate(五)——面向对象查询语言和锁

Wesley13
• 阅读 638

Hibernate 做了数据库中表和我们实体类的映射,使我们不必再编写 sql 语言了。但是有时候查询的特殊性,还是需要我们手动来写查询语句呢, Hibernate 框架为了解决这个问题给我们提供了 HQL ( Hibernate  Query  Language ) 面向对象的查询语言,和 QBC ( Query by Criteria

)完全面向对象的查询,这里简单总结一下如何是面向对象来编写ql语句呢。

一,HQL,Hibernate框架中的查询语言,是一种面向对象查询语言,和sql语句还是非常类似的,就是将sql语句中的表改成实体名,字段改为属性名即可,其它基本都很相似的。主要用的是Query这个对象。返回值可以使用list,iterate(多值),uniqueResult(单值)等属性进行取值。下边看几个小例子:

1,模糊查询+list迭代:

[java] view plain copy print ? Hibernate(五)——面向对象查询语言和锁  Hibernate(五)——面向对象查询语言和锁

  1. String key = "san";
  2. Query query = session.createQuery("FROM Student s where  s.sname like ?"); //HQL语句。看里边都是使用类名和属性名代替了数据库中的表和字段
  3. query.setParameter(0, "%"+key+"%"); //参数索引从0开始。
  4. //query.setString(0, "%"+key+"%");
  5. List sts =  query.list();
  6. for(Student s : sts){
  7. System.out.println(s.getSname());
  8. }

2,iterate相当于集合中的迭代器,Hibernate框架会先查询符合条件的所有id值,然后根据每个id去查询每一条记录,这样我们查询N条件记录时,框架帮我们发送了N+1条语句,这也就是大家经常讨论的N+1问题。这个我们可以通过实际的例子实验一下:

[java] view plain copy print ? Hibernate(五)——面向对象查询语言和锁  Hibernate(五)——面向对象查询语言和锁

  1. Query query = session.createQuery("from Student s");

  2. Iterator it = query.iterate();

  3. while(it.hasNext()){

  4. Student s = (Student)it.next();

  5. System.out.println(s.getSname());

  6. }

3,返回结果是一个的话,可以使用uniqueResult值来获取:

[java] view plain copy print ? Hibernate(五)——面向对象查询语言和锁  Hibernate(五)——面向对象查询语言和锁

  1. public static void testSelect8(Session session){
  2. Query query = session.createQuery("from Student s where s.sid=1");
  3. Student s = (Student)query.uniqueResult();
  4. System.out.println(s.getSname());
  5. }

4,当然Query对象也支持update,delete,insert,但是这些操作会立即对数据库的数据进行操作,而不对缓存中的数据进行操作,那么在支持缓存时,数据可能会出现冲突,所以使用要慎用。

[java] view plain copy print ? Hibernate(五)——面向对象查询语言和锁  Hibernate(五)——面向对象查询语言和锁

  1. Query query = session.createQuery("update Student s set s.sname='张三123' where s.sid=1" );
  2. int i = query.executeUpdate();
  3. if(i==1){
  4. System.out.println("更新成功");
  5. }

5,这里说一下两者和缓存之间的关系吧:

iterate方法默认是支持缓存的,只要我们的框架配置了二级缓存的支持,iterate方法也是会支持的。

list呢?默认是不支持缓存的,如何让它支持缓存呢,这里需要我们的配置,这里简单看一下支持缓存的配置吧?

a,首先需要引入jar包和对应的xml配置文件,这里的jar包及配置文件和二级缓存的jar包是一样的:ehcache-1.2.3.jar,ehcache.xml

b,在hibernate.cfg.xml中启用查询缓存(注意不是二级缓存):

[html] view plain copy print ? Hibernate(五)——面向对象查询语言和锁  Hibernate(五)——面向对象查询语言和锁

  1. <propertynamepropertyname="hibernate.cache.use_query_cache">true</property>

c,让框架识别缓存组件,和二级缓存中是一样的:

[html] view plain copy print ? Hibernate(五)——面向对象查询语言和锁  Hibernate(五)——面向对象查询语言和锁

  1. <propertynamepropertyname="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

   

这样配置了以后,list就支持缓存了,此查询缓存是支持一级查询和二级查询的。

二,QBC(Query by Criteria),是通过利用Criteria对象来进行查询的,更适合做不定参数查询的情况,这里举一个简单例子,

[java] view plain copy print ? Hibernate(五)——面向对象查询语言和锁  Hibernate(五)——面向对象查询语言和锁

  1. Criteria cra = session.createCriteria(Student.class);
  2. // _ 匹配一个字符,   % 匹配多个字符
  3. cra.add(Restrictions.like("sname", "%s%"));
  4. cra.addOrder(Order.desc("sid"));
  5. List sts = cra.list();
  6. for(Student s : sts){
  7. System.out.println(s.getSname());

上边两项是Hibernate框架中,面向对象编写SQL语句的写法,总体上和sql语句的编写是类似的,但是更加面向对象,对一些功能的编写更加容易,我们可以根据不同情况进行不同的选择使用即可。

三,我们这里来看一下Hibernate中的锁机制吧,在此框架中锁机制包括悲观锁和乐观锁!

1,悲观锁:对于一些数据我们是不能同时去修改的,否则就会出现数据的错误,在数据库中我们可以通过行级锁select……for update进行对数据的锁定,避免的。而在框架中就是通过悲观锁的。为什么叫它悲观锁呢?因为发生这种同时修改数据的几率是非常非常小,而此种锁却一直加上了,所以它是一种悲观者的身份来做的事。所以称为悲观锁。看一下怎么使用吧!

设置LockMode.UPGRADE参数,那么只有当前事务提交后,另外的事务才能够查询这个数据。这种悲观锁的性能比较底。

          Account account =(Account)session.get(Account.class, 1 , LockMode.UPGRADE);

2,乐观锁:其实就是以乐观人的态度来解决这种数据同时修改的问题。解决原理是,当事务不同时发生时,没有锁,如果事务同步发生了,它的锁就起作用了。所以来说,它只是在这种几率很小的情况发生时才会加锁,所以叫乐观锁。它的性能大大的提高了。

a,实现方式:时间戳和版本号(Hibernate框架实现的)

b,在我们需要加乐观锁对应的数据上,添加ptimistic-lock="version"属性:

[html] view plain copy print ? Hibernate(五)——面向对象查询语言和锁  Hibernate(五)——面向对象查询语言和锁

  1. <hibernate-mapping>

  2. <class name="com.bjpowernode.hibernate.pojo.Account" table="t_account" optimistic-lock="version">

  3. <id name="aid" column="aid">

  4. <generator class="assigned"/>

  5. </id>

  6. <version name="ver" column="version"></version>

  7. <property name="money"/>

  8. </class>

  9. </hibernate-mapping>

这样,框架会自动为我们调用版本号,来进行乐观锁的的管理。功能还是非常强大的。尤其对于一些特别需要安全的数据,例如银行卡的余额等等。

综上,为Hibernate中面向对象查询语句,与锁的简单总结。感觉Hibernate的功能还是非常强大的,需要我们不断的挖掘,钻研……

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
JavaEE之Hibernate(开放源代码的对象关系映射框架)
Hibernate(开放源代码的对象关系映射框架)1.简介Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随
Stella981 Stella981
3年前
Hibernate原生SQL查询
Hibernate除了支持HQL查询外,还支持原生SQL查询。对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取这个接口。该接口是Query接口的子接口。执行SQL查询步骤如下:1、获取HibernateSession对象2、编写SQL语句3、通过Session的createS
Stella981 Stella981
3年前
Hibernate4教程六:性能提升和二级缓存
抓取策略(fetchingstrategy)是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候,Hibernate如何获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL或条件查询(CriteriaQuery)中重载声明。Hibernate4定义了如下几种抓取策略:1:连接抓取(J
Stella981 Stella981
3年前
Hibernate中get()和load()的区别
Hibernate中根据Id单条查询获取对象的方式有两种,分别是get()和load(),来看一下这两种方式的区别。1\.get()使用get()来根据ID进行单条查询:Userusersession.get(User.class,"1");当get()方法被调用的时候就会立即发出SQL语句:Hiberna
Stella981 Stella981
3年前
Hibernate反射DAO模式
在持久层框架中,如果我们要像简单的JDBC连接数据库那样写一个通用的Dao方法的话,那么把JDBC简单的业务逻辑搬到hibernate持久层框架中,当然是不可能的,这里主要的问题就在于hibernate持久层框架中,因为它不是像JDBC那样简单的增删改查的编写,而是要针对实体类映射配置文件来对照数据库表字段进行操作,而且操作是面向对象的查询,不是简单的sql
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这