hibernate中的几个重要方法以及调用.doc_第1页
hibernate中的几个重要方法以及调用.doc_第2页
hibernate中的几个重要方法以及调用.doc_第3页
hibernate中的几个重要方法以及调用.doc_第4页
hibernate中的几个重要方法以及调用.doc_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Hibernate查询首先介绍get()和load()方法的区别:get()方法和load()方法的区别主要在于对二级缓存的使用上。load()方法会使用二级缓存,而get()方法在一级缓存没有找到会直接查询数据库,不会去二级缓存中查找。get():如果在数据库中没有记录会返回空,get()无论如何都会返回数据.load():如果数据库中没有记录会抛出异常,如果有数据返回的是一个代理对象。get()方法默认不支持lazy(延迟加载)功能,而load支持延迟加载get()方法在查询不到数据时,返回null,而load因为支持延迟加载,只有在使用对象时才加载,所以如果数据库中不在数据load会抛出异常(org.hibernate.ObjectNotFoundException)。get()和load()只根据主键查询,不能根据其它字段查询,如果想根据非主键查询,可以使用HQLlist和iterator()方法之间的区别:(N+1?)list()方法在执行时,直接运行查询结果所需要的查询语句。iterator()方法则是先执行得到对象ID的查询,然后在根据每个ID值去取得所要查询的对象。因此:对于list()方式的查询通常只会执行一个SQL语句,而对于iterator()方法的查询则可能需要执行N+1条SQL语句(N为结果集中的记录数).结果集的处理方法不同:list()方法会一次活的所有的结果集对象,而且他会依据查询的结果初始化所有的结果集对象。如果在结果集非常庞大的时候会占据非常多的内存,甚至会造成内存溢出的情况发生。iterator()方法在执行时不会一次初始化所有的对象,而是根据对结果集的访问情况来初始化对象。一次在访问中可以控制缓存中对象的数量,以避免占用过多的缓存,导致内存溢出情况的发生。HQL:HQL是一种面向对象的查询语言,HQL的操作对象是类、实例和属性等。SQL:sql的操作对象是数据表和列等数据对象。Hql是完全面向对象的查询语言,因此可以支持继承和多条等特征。HQL查询依赖于Query类,每个Query实例对应一个查询对象。定参数的功能,Query 接口才是真正的HQL查询接口。/创建一个Query 对象Java代码1. Queryquery=session.createQuery(fromC=:customerNameandc.age=:customerAge);/动态绑定参数Java代码1. query.setString(customerName,Tom);2. query.setInteger(customerAge,21);/执行查询语句,返回结果Java代码1. Listresult=query.list();HQL查询步骤:1:获取Hibernate Session对象。2:编写HQL语句。3:以HQL语句作为参数,调用Session的createQuery方法创建查询对象。4:如果HQL语句包含参数,调用Query的setXXX()方法为参数赋值。5: 调用Query对象的list等方法遍历查询结果。Query还包含两个方法:Java代码1. setFirstResult(intfirstResult):/设置返回的结果集从第几条记录开始。2. setMaxResults(intmaxResults):/设置本次查询返回的结果数。实体的删除和更新。投影查询:只查询属性的一部分。 查询一个属性返回的是字符串 查询二个字段返回的是数组动态构造查询:主要用于几十个表查询; 要构建一个新的对象,要加上一个构造函数; 在new对象的时候要加上包名不要使用count(*) 要count(持久化对象)分组与排序:Order by子句可以通过asc或desc关键字排序 如:Java代码1. formUseruOasc,u.agedesc;Group by子句与统计查询:如:Java代码1. Stringhql=selectcount(u),u.agefromUserugroupbyu.agehavingcount(u)10;2. Listlist=session.createQuery(hql).list();标准的SQL聚合函数都可以在HQL语句中使用,比如:count(),sum(),max(),min(),age()等连接查询:内连接:inner join左外连接:left outer join右外连接:right outer join全连接:full join(不常用)迫切外连接:left outer join fetch,left joinfetch:用于一次性获取连接数据,特别是集合数据。减少与数据库交互的次数。left out join:使用做外连接位于left join 左侧表的所有记录及对应的order类的记录信息都将显示出来。right out join:与 left out join 正好相反,right out join 返回的是HQL右侧表中的所有记录以及对应的Customer对象记录信息。获取集合数据的四种方式:1:Hibernate.initialize(user.getOrder();2:user.getOrder().size();3:左右迫切连接4:高级过滤器条件查询语句(Criteria Queries):利用对象进行对象查询。 主要的接口有:Criteria、Criterion和expression_r和Restrictions类组成。能够支持在运行时动态生成SQL语句。条件查询步骤:1:通过seesion的CreateCriteria()方法,创建一个Criteria对象2:设置查询对象,name指对象的属性3:把查询条件添加到Criteria对象中4:执行list()查询返回结果。条件查询通过三个类完成:Criteria:代表一次查询.Criterion:代表一个查询条件.Restrictions:产生查询条件的工具类.本地sql查询:使用手写的SQL来完成所有的createupdatedelete操作也包括存储过程本地sql步骤:1:通过session创建一个SqlQuery对象。2:编写sql语句3:以SQL语句作为参数,调用Session的createSQLQuery方法创建查询对象4:如果SQL语句包含参数,则调用Query的setXX方法为参数赋值5:调用SQLQuery对象的addEntity或addScalar方法,将选出的结果与实体或标量值关联.如:HQL的sqlJava代码1. Stringsql=selectc.c_idasc.id,c.c_fromCUSTOMERcwherec.id=1;注意:如果使用*,表的别名和类的别名要一致Java代码1. Stringsql1=selectc.*fromCUSTOMERcwherec.c_id=2;如:条件查询的sqlJava代码1. SQLQueryquery=session.createSQLQuery(sql);2. query.addEntiy(c,Customer.class);多态查询:多态查询是指可以查询到当前类及所有子类的实例,HQL和条件查询都支持多态查询。如:hql语句查询出所有的持久化对象Java代码1. Queryquery=session.createQuery(fromjava.lang.object);2. System.out.println(query.list();HQL支持多态查询,多态查询是指查询出当前类及所有子类的实例,session.createQuery(from Employee); or session.createCriteria(Employee.class);如果Employee类有两个子类:HourlyEmployee和SalariedEmployee,那么这个查询语句会查出所有的Employee实例,以及HourlyEmployee类和SalariedEmployee类的实例。Java代码1. session.createQuery(fromHourlyEmployee);2. session.createCriteria(HourlyEmployee.class);/只检索子类查询结果集排序:Hql与条件查询都支持查询结果集排序,只是HQL采用Order by关键字,而条件查询采用order类进行查询结果排序。分页查询:分页查询是数据库应用中常见的处理方式,Query和Criteia接口都提供了用于分页查询的方法.Java代码1. setFistResult(int):/指定从哪一个对象开始查询,参数是索引位置从0开始。2. setMaxResults(int):/指定一次最多查询的对象数量。子查询: 1:查询有一个订单以上的客户。如:Java代码1. fromCustomercwhere11如果子查询返回多条记录,可以使用关键字量化:1:all 2:any 3:some 4:in 5:exists如:Java代码1. /返回所有订单价格小于100的客户2. fromCustomercwhere100all(selecto.priceformc.orderso)3. /返回有一条订单的价格小于100的客户4. fromCustomercwhere100any(selecto.pricefromc.orderso)5. /返回有一条订单的价格等于100的客户6. fromCustomercwhere100=some(selecto.pricefromc.ordero)7. 8. /返回有一条订单的价格等于100的客户9. fromCustomercwhere100=any(selecto.privefromc.orderso)10. /返回有一条订单的价格等于100的客户11. fromCustomercwhere100in(selecto.pricefromc.orderso)参数绑定:1:传统的JDBC的参数绑定 如:Java代码1. PrepareStatementpre=connection.prepare(select*fromU=?);2. pre.setString(1,Zhao);3. ResultSetrs=pre.executeQuery();Hibernate参数绑定:在hibernate中有4种参数绑定方式1:按参数名称(命名参数)绑定,在语句中定义命名参数要用:开头2:按参数位置绑定3:Hql查询中可以通过setParameter()方法绑定任意类型的参数4:setProperties()方法,将命名参数与一个对象的属性值绑定在一起如:参数:开头Java代码1. Queryquery=session.createQuery(fromU=customernameanduser.age=:customerage);2. query.setString(customername,name);3. query.setInteger(customerage,age);如:参数位置绑定Java代码1. Queryquery=session.createQuery(fromU=?anduser.age=?);2. query.setString(0,name);3. query.setInteger(1,age);如:setParameter他有三个参数一般写两个参数Java代码1. Stringhql=fromU=:customername;2. Queryquery=session.createQuery(hql);3. query.setParameter(customername,name,Hibernate.STRING);如:setPropertiesJava代码1. Customercustomer=newCustomer();2. customer.setName(sdsd);3. customer.setAge(99);4. Queryquery=session.createQuery(fromC=:nameandc.age=:age);5. query.setProperties(customer);定义命名查询:命名的SQL语句不是放在程序中,而是放在配置文件中,这种方式是以松耦合的方式配置SQL语句,可以提高程序解耦.在Customer.hbm.xml配置文件中Java代码1. 2. 3. 程序中的代码:Java代码1. Queryquery=session.getNamedQuery(findCustomer);2. query.setString(name,tiger);3. Listlist=query.list();命名的SQL语句:Java代码1. 2. 3. 4. 5. selectc.*6. fromCustomerClike刘德华7. sql_query是hibernate-mapping元素的子元素,因此可以直接通过session访问缓存是位于应用程序与物理数据源之间,用于临时存放复制数据的内存区域,目的是为了减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能. Hibernate在查询数据时,首先到缓存中去查找,如果找到就直接使用,找不到的时候就会从物理数据源中检索,所以,把频繁使用的数据加载到缓存区后,就可以大大减少应用程序对物理数据源的访问,使得程序的运行性能明显的提升.缓存分两级,一级session缓存,就是常说的一级缓存;二级应用缓存(二级缓存);一级缓存,一级缓存依赖于session,在一个session中就是一个缓存,当session失效时,缓存消失。/*两个session两次加载*/Java代码1. publicvoidloadBookAgain()2. Sessionsession=HibernateSessionFactory.getSession();3. Bookbook1=(Book)session.get(Book.class,6);4. Bookbook2=(Book)session.get(Book.class,6);5. session.close();6. 7. /Sessionsession1=HibernateSessionFactory.getSession();8. /Bookbook2=(Book)session1.get(Book.class,6);9. /session1.close();10. 在一个session里面查询两次相同的book,只会执行一次sql。但若放在不同的session中,将会执行两次数据库查询。解决问题的办法就是用二级缓存。二级缓存是SessionFactory级别的全局缓存,它底下可以使用不同的缓存类库,比如ehcache、oscache等。 参考/topic/249465 不是所有的数据都适合放在二级缓存中 下面这几种情况就不适合加载到二级缓存中: 1.经常被修改的数据 2.绝对不允许出现并发访问的数据 3.与其他应用共享的数据 下面这己种情况合适加载到二级缓存中: 1.数据更新频率低 2.允许偶尔出现并发问题的非重要数据 3.不会被并发访问的数据 4.常量数据 5.不会被第三方修改的数据配置二级缓存比较简单,以ehcache为例:添加缓存文件ehcache-hibernate-local.xmlJava代码1. 2. 3. 4. 5. 9. 10. 12. 13. maxElementsInMemory为缓存对象的最大数目, eternal设置是否永远不过期, timeToIdleSeconds对象处于空闲状态的最多秒数, timeToLiveSeconds对象处于缓存状态的最多秒数 。 在实体bean的hbm.xml文件中加上缓存配置:Java代码1. 3. 现在大部分的hibernate应用不再写实体映射配置文件,那么就在实体bean中加上 /默认的缓存策略.Java代码1. Cache(usage=CacheConcurrencyStrategy.READ_WRITE) 在hibernate定义sessionFactory中加上查询缓存配置: Java代码1. 2. org.hibernate.cache.EhCacheProvider3. Java代码1. true2. 4. /ehcache-hibernate-local.xml5. 如果项目试用了spring,那么相应配置为:Java代码1. 2. 3. $hibernate.dialect4. $hibernate.show_sql5. $hibernate.format_sql6. org.hibernate.cache.EhCacheProvider7. /ehcache-hibernate-local.xml8. 9. 两种配置基本一致。这个时候在按实体的ID来查询的时候即使不在一个session中,hibernate也只是执行一次sql。查询缓存做到现在,有一点效果,但基本还是个摆设。看下面代码:Java代码1. publicvoidlistBookTwice()2. Stringhql=fromBook;3. Sessionsession=HibernateSessionFactory.getSession();4. Queryq=session.createQuery(hql);5. Listlist1=q.list();6. Listlist2=q.list();7. session.close();同一个query。list了两次,按照之前的效果,应该是执行一个sql。事实是,他要去查两次,在一个query尚且如此,两个不用说,肯定也是没有用到缓存了。难道缓存失效了?呵呵,其实是因为我们虽然配置了缓存,但是在query级却没有设置缓存,如果需要query缓存,则需要手工写入:q.setCacheable(true);来激活查询缓存。修改代码如下:Java代码1. publicvoidlistBookTwice()2. Stringhql=fromBook;3. Sessionsession=HibernateSessionFactory.getSession();4. Queryq=session.createQuery(hql);5. q.setCacheable(true);6. Listlist1=q.list();7. for(Bookb:list1)8. System.out.println(b.getBname()+-list1);9. 10. /Listlist2=q.list();11. session.close();12. 13. Sessionsession2=HibernateSessionFactory.getSession();14. Queryq2=session2.createQuery(hql);15. q2.setCacheable(true);16. Listlist2=q2.list();17. for(Bookb:list2)18. System.out.println(b.getBname()+-list2);19. 20. session2.close();21. 在两个session立分别list查询,ok,只输出一条sql。说明二级缓存在list查询的时候也起作用了。那hibernate是根据什么来缓存list呢,参考:/topic/18904对于查询缓存来说,缓存的key是根据hql生成的sql,再加上参数,分页等信息(可以通过日志输出看到,不过它的输出不是很可读,最好改一下它的代码)。比如hql:from Cat c where like ?生成大致如下的sql:select * from cat c where like ?参数是tiger%,那么查询缓存的key*大约*是这样的字符串(我是凭记忆写的,并不精确,不过看了也该明白了):select * from cat c where like ? , parameter:tiger%这样,保证了同样的查询、同样的参数等条件下具有一样的key。现在说说缓存的value,如果是list方式的话,value在这里并不是整个结果集,而是查询出来的这一串ID。也就是说,不管是list方法还是iterate方法,第一次查询的时候,它们的查询方式很它们平时的方式是一样的,list执行一条sql,iterate执行1+N条,多出来的行为是它们填充了缓存。但是到同样条件第二次查询的时候,就都和iterate的行为一样了,根据缓存的key去缓存里面查到了value,value是一串id,然后在到class的缓存里面去一个一个的load出来。这样做是为了节约内存。可以看出来,查询缓存需要打开相关类的class缓存。list和iterate方法第一次执行的时候,都是既填充查询缓存又填充class缓存的。这里还有一个很容易被忽视的重要问题,即打开查询缓存以后,即使是list方法也可能遇到1+N的问题!相同条件第一次list的时候,因为查询缓存中找不到,不管class缓存是否存在数据,总是发送一条sql语句到数据库获取全部数据,然后填充查询缓存和class缓存。但是第二次执行的时候,问题就来了,如果你的class缓存的超时时间比较短,现在class缓存都超时了,但是查询缓存还在,那么list方法在获取id串以后,将会一个一个去数据库load!因此,class缓存的超时时间一定不能短于查询缓存设置的超时时间!如果还设置了发呆时间的话,保证class缓存的发呆时间也大于查询的缓存的生存时间。这里还有其他情况,比如class缓存被程序强制evict了,这种情况就请自己注意了。另外,如果hql查询包含select字句,那么查询缓存里面的value就是整个结果集了。可以理解为hibernate缓存了每次查询的hql语句作为缓存map的key,将对应对象的id作为value缓存,每次遇到相同的hql,就将id取出来,如果在缓存里面有对象,就从缓存取,没有的话就去数据库load缓存什么时候更新呢?看代码:Java代码1. publicvoidupdate()2. Sessionsession=HibernateSessionFactory.getSession();3. Transactiontran=session.beginTransaction();4. tran.begin();5. Bookb=(Book)session.get(Book.class,7);6. b.setIsbn(567890);7. session.saveOrUpdate(b);8. mit();9. session.close();10. 11. publicvoidlistBookTwice()12. Stringhql=fromBook;13. Sessionsession=HibernateSessionFactory.getSession();14. Queryq=session.createQuery(hql);15. q.setCacheable(true);16. Listlist1=q.list();17. for(Bookb:list1)18. System.out.println(b.getBname()+-+b.getIsbn()+-list1);19. 20. session.close();21. 22. 23. publicvoidlistBookAg

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论