在WEB应用中使用了Hibernate,使用session.createQuery().list()方法查询时,每次均会发SQL语句;使用session.createQuery().iterate()方法查询时使用缓存的,也就是第一次查询时会将每个对象缓存,以后查询只按ID查.
Session session = HibernateSessionFactory.getSession() ;
//Transaction tx = session.beginTransaction() ;
String queryString = "from Param";
Query queryObject = session.createQuery(queryString);
List list = queryObject.list() ;
//tx.commit() ;
if(list!=null && list.size()>0){
for(int i=0;i<list.size();i++){
Param param = (Param)list.get(i) ;
System.out.println(param.getId()+"|"+param.getValue());
}
}
try {
Class.forName("com.mysql.jdbc.Driver") ;
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/common","root","root") ;
Statement stmt = conn.createStatement() ;
stmt.execute("update param set value=''") ;
stmt.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
session = HibernateSessionFactory.getSession() ;
//tx = session.beginTransaction() ;
queryObject = session.createQuery(queryString);
list = queryObject.list() ;
//tx.commit() ;
if(list!=null && list.size()>0){
for(int i=0;i<list.size();i++){
Param param = (Param)list.get(i) ;
System.out.println(param.getId()+"|"+param.getValue());
}
}两次查询的结果一样.但中间的JDBC代码部分确实已经将value值改了,请问大家这是什么原因啊?感觉list()也缓存了,但确实是发出了两句select查询.使用iterate()第二次查询只查了ID.
Session session = HibernateSessionFactory.getSession() ;
//Transaction tx = session.beginTransaction() ;
String queryString = "from Param";
Query queryObject = session.createQuery(queryString);
List list = queryObject.list() ;
//tx.commit() ;
if(list!=null && list.size()>0){
for(int i=0;i<list.size();i++){
Param param = (Param)list.get(i) ;
System.out.println(param.getId()+"|"+param.getValue());
}
}
try {
Class.forName("com.mysql.jdbc.Driver") ;
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/common","root","root") ;
Statement stmt = conn.createStatement() ;
stmt.execute("update param set value=''") ;
stmt.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
session = HibernateSessionFactory.getSession() ;
//tx = session.beginTransaction() ;
queryObject = session.createQuery(queryString);
list = queryObject.list() ;
//tx.commit() ;
if(list!=null && list.size()>0){
for(int i=0;i<list.size();i++){
Param param = (Param)list.get(i) ;
System.out.println(param.getId()+"|"+param.getValue());
}
}两次查询的结果一样.但中间的JDBC代码部分确实已经将value值改了,请问大家这是什么原因啊?感觉list()也缓存了,但确实是发出了两句select查询.使用iterate()第二次查询只查了ID.
解决方案 »
- 请教一个关于java rmi远程调用 传递自定义对象的问题
- 如何绘制一个曲线图显示在jsp页面。
- struts2文件上传怪异问题
- 如何把数据保存为树形结构
- 如何关闭tomcat自带的manager服务?
- org.xml.sax.SAXParseException: White spaces are required between publicId and systemId
- 怎样用JB2005打jar包了?
- 急!怎样实现jsp与php的通信?
- 《J2EE 构建企业系统-专家级解决方案》5折抛售
- 一个关于EJB的简单问题,请问EJBObject 类属于哪个包内?
- 一个新手的问题
- 每天一问,关于论坛问题
Query 接口的iterator和list都能执行SQL,但前者在某些情况下能稍微提高查询性能。比如:
Query query1 = session.createQuery("from Customer c");
List result = query1.list();Query query2 = session.createQuery("from Customer c where c.age<30");
List result2 = query2.list();当第二次执行查询时Hibernate生成的SQL为: select id,name ,age from customer wehre age < 30;
由于在查询第二条语句时,其对应的Customer结果已经存在于Session缓存中,那么在进行第二条查询时,hiberante不需要创建新的Customer对象,只需要根据查询结果中的ID字段值返回缓存中匹配的Customer对象即可。因此第二条SQL语句可以为: SELECT id from cunstomer where age <30;那么如何达到这个效果呢,那就将 query2的 查询改为 query2.iterator()即可。”
所以iterator的查询,应该是要跟缓存比较的,如果之前已经有缓存相关数据,那么在查询时就只查询出OID也就是对象ID,一般为表主键。然后根据OID从缓存中得到相应的整条数据对象。因此两者没什么,至于效率上,只有在表数据量比较大,字段比较多的时候才能体现出来。一般情况下没什么区别。
呵呵..是同一个session,简单描述一下情况就是:先使用hibernate query.list()查询,接着外部JDBC更新了数据,然后hibernate再查询,查询的数据仍为未更新的数据!
我弄了两段你对比下
public void testList(){
Session session = HibernateSessionFactory.getSession() ;
String queryString = "from Param";
Query queryObject = session.createQuery(queryString);
List list = queryObject.list() ;
//此处查询语句为:select param0_.id as id2_, param0_.value as value2_ from common.param param0_
//打印list,如:
//id value
//1 aa
//2 bb
//
//此处使用JDBC更新value值,省略代码
//
session = HibernateSessionFactory.getSession() ;
queryObject = session.createQuery(queryString);
list = queryObject.list() ;
//此处查询语句仍为:select param0_.id as id2_, param0_.value as value2_ from common.param param0_,
//打印list仍为(注:JDBC更新后的数据hibernate没有读出来,看hibernate文档似乎又不是缓存,使用queryObject.list()才缓存)
//id value
//1 aa
//2 bb
} public void testIterate(){
Session session = HibernateSessionFactory.getSession() ;
String queryString = "from Param";
Query queryObject = session.createQuery(queryString);
Iterator it = queryObject.iterate() ;
//此处查询语句为:select param0_.id as col_0_0_ from common.param param0_ 查找出ID
while(it.hasNext()){
Param param = (Param)it.next();
//此处查询语句为:select param0_.id as id2_0_, param0_.value as value2_0_ from common.param param0_ where param0_.id=? 根据ID找出对象并缓存
System.out.println(param.getId()+"|"+param.getValue());
}
//
//此处使用JDBC更新value值,省略代码
//
session = HibernateSessionFactory.getSession() ;
queryObject = session.createQuery(queryString);
it = queryObject.iterate() ;
//此处查询语句为:select param0_.id as col_0_0_ from common.param param0_ 直接查出缓存对象
while(it.hasNext()){
Param param = (Param)it.next();
System.out.println(param.getId()+"|"+param.getValue());
}
}
先不管是不是查询缓存,不管是list还是iterator都要查询缓存的。但iterator是先查询标识,再根据标识查实例。确实是多次查询,以就是LZ表述的现象,以下是iterator的API描述/**
* Return the query results as an <tt>Iterator</tt>. If the query
* contains multiple results pre row, the results are returned in
* an instance of <tt>Object[]</tt>.<br>
* <br>
* Entities returned as results are initialized on demand. The first
* SQL query returns identifiers only.<br>
*
* @return the result iterator
* @throws HibernateException
*/
public Iterator iterate() throws HibernateException;