Hibernate作了数据库中表和咱们实体类的映射,使咱们没必要再编写sql语言了。可是有时候查询的特殊性,仍是须要咱们手动来写查询语句呢,Hibernate框架为了解决这个问题给咱们提供了HQL(Hibernate Query Language)面向对象的查询语言,和QBC(Query by Criteria)彻底面向对象的查询,这里简单总结一下如何是面向对象来编写ql语句呢。 java
一,HQL,Hibernate框架中的查询语言,是一种面向对象查询语言,和sql语句仍是很是相似的,就是将sql语句中的表改为实体名,字段改成属性名便可,其它基本都很类似的。主要用的是Query这个对象。返回值可使用list,iterate(多值),uniqueResult(单值)等属性进行取值。下边看几个小例子: node
1,模糊查询+list迭代: sql
String key = "san"; Query query = session.createQuery("FROM Student s where s.sname like ?"); //HQL语句。看里边都是使用类名和属性名代替了数据库中的表和字段 query.setParameter(0, "%"+key+"%"); //参数索引从0开始。 //query.setString(0, "%"+key+"%"); List<Student> sts = query.list(); for(Student s : sts){ System.out.println(s.getSname()); }
2,iterate至关于集合中的迭代器,Hibernate框架会先查询符合条件的全部id值,而后根据每一个id去查询每一条记录,这样咱们查询N条件记录时,框架帮咱们发送了N+1条语句,这也就是你们常常讨论的N+1问题。这个咱们能够经过实际的例子实验一下: 数据库
Query query = session.createQuery("from Student s"); Iterator<Student> it = query.iterate(); while(it.hasNext()){ Student s = (Student)it.next(); System.out.println(s.getSname()); }
3,返回结果是一个的话,可使用uniqueResult值来获取: 缓存
public static void testSelect(Session session){ Query query = session.createQuery("from Student s where s.sid=1"); Student s = (Student)query.uniqueResult(); System.out.println(s.getSname()); }
4,固然Query对象也支持update,delete,insert,可是这些操做会当即对数据库的数据进行操做,而不对缓存中的数据进行操做,那么在支持缓存时,数据可能会出现冲突,因此使用要慎用 安全
Query query = session.createQuery("update Student s set s.sname='张三123' where s.sid=1" ); int i = query.executeUpdate(); if(i==1){ System.out.println("更新成功"); }
5,这里说一下二者和缓存之间的关系吧: session
iterate方法默认是支持缓存的,只要咱们的框架配置了二级缓存的支持,iterate方法也是会支持的。 app
list呢?默认是不支持缓存的,如何让它支持缓存呢,这里须要咱们的配置,这里简单看一下支持缓存的配置吧? 框架
a,首先须要引入jar包和对应的xml配置文件,这里的jar包及配置文件和二级缓存的jar包是同样的:ehcache-1.2.3.jar,ehcache.xml ide
b,在hibernate.cfg.xml中启用查询缓存(注意不是二级缓存):
<!--启用查询缓存 --> <propertynamepropertyname="hibernate.cache.use_query_cache">true</property>
c,让框架识别缓存组件,和二级缓存中是同样的:
<!--让框架识别ehcache缓存组件 --> <propertynamepropertyname="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
这样配置了之后,list就支持缓存了,此查询缓存是支持一级查询和二级查询的。
二,QBC(Query by Criteria),是经过利用Criteria对象来进行查询的,更适合作不定参数查询的状况,这里举一个简单例子,
Criteria cra = session.createCriteria(Student.class); // _ 匹配一个字符, % 匹配多个字符 cra.add(Restrictions.like("sname", "%s%")); cra.addOrder(Order.desc("sid")); List<Student> sts = cra.list(); for(Student s : sts){ 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"属性:
<hibernate-mapping> <!-- optimistic-lock="version" 使用乐观锁 --> <class name="com.bjpowernode.hibernate.pojo.Account" table="t_account" optimistic-lock="version"> <id name="aid" column="aid"> <generator class="assigned"/> </id> <!-- 版本号字段 ,这里须要咱们在对应的pojo类中添加对应的verget,set方法--> <version name="ver" column="version"></version> <property name="money"/> </class> </hibernate-mapping>
这样,框架会自动为咱们调用版本号,来进行乐观锁的的管理。功能仍是很是强大的。尤为对于一些特别须要安全的数据,例如银行卡的余额等等。
综上,为Hibernate中面向对象查询语句,与锁的简单总结。感受Hibernate的功能仍是很是强大的,须要咱们不断的挖掘,钻研……