Hibernate 查询结果的展现


我们使用hibernate(以下简称h)来管理数据库表的关联关系,基本的原理其实是很简单的,就是将数据库中表之间的关联转移到了实体bean的类之间,配置好了以后h就可以帮我们维持这种关联关系了。这的确带来了很大的方便,我们可以在我们的程序中以hql来面向对象的获取或保存数据了,例如以前我们要查询一个班级里面的学生的信息,自己写sql的话需要关联2张表,而且还要自己手动的将查询到的数据一个一个的取出来,然后封装到我们的bean里面去最后才能字啊jsp中显示出来,这个过程是很繁琐的,有了h,我们就可以不用在sql显式的写这种关联关系了,我们选择将这种关联关系写到h的映射文件中去,这样一来h就帮我们维护这种关系了,我们需要查询班级里面的学生的信息的时候,只要通过hql: from Class  as c  where c.id=:id;就可以得到具体的一个班级的实体对象(假设是c),接着Set<Student> students= c.getStudents();就可以得到该班级里面的所有的学生了。整个过程没有join等任何关联操作,以为这个关联已经由h帮我们维护了,所以我们就可以不管了。

通过上面我们知道,Hibernate是通过对象包含对象这样的方式来维护关系的,那么当我们需要查询关联对象的时候,先通过Hibernate得到主对象,再调用主对象的get×得到关联对象,就可以获取关联信息了,然后组装数据到jsp上去显示。 我们可以简单的写成:hql=“select new map(c.id as id ,c.name as name,c.students[0].name as  studentname) from Class as  c  where c.id=:id”; 这样就同时完成了数据的查询和组装。将查询到的数据组装到一个map中,as 后面的就是 map的key,map的值就是查询出来的数据了。这种数据组装方式比:

while (it.hasNext()) { 
10 Object[] tuple = (Object[]) it.next(); 
11 Members members = (Members) tuple[ 0 ]; 
12 String className = (String) tuple[ 1 ]; 

要简洁很多。

当然,我们也可以定义自己的实体类来容纳查询出的数据:

selectnew NewMembers(members, classInfo.className) " + 
3 " from Members members, ClassInfo classInfo " + 
4 " where members.level = classInfo.classCode " 

也可以 使用hibernateapi 函数 setResultTransformer 将查询结果存放到我们自定义的bo对象中去:

String sql = "select u.userName as userName p.title as title ,p.addTime as addTime from user as u,post as p where u.id=p.userId"
Query q = factory.getCurrentSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(PostVO.class));
关于数据组装,有很多方法,不一而论。
我们下面要讨论的是,h在涉及到3张或3张以上的表的复杂的查询的时候,如何使用的问题。
我们知道2张或者一张表的情形使用我们上面介绍的方式就足够了,但是对3张以上的表关联的复杂查询,我们则要比较2中方式的好坏了:
一种方式是仍然将表关系通过配置映射文件交给h来管理,这样一来我们不仅仅要在配置文件里配置多个关系,而且在对应的实体类里面也要加入关联属性,在查询的时候得到主实体对象以后还有多次调用其属性来获取关联表的信息,这样不是不可以,但是是比较繁琐的,稍微不注意就容易出现错误。
如果要查询的表多于5张,最好的建议就是使用native sql来做,也就是通过直接执行sql语句来查询,表间的关联关系直接在sql语句里面写明,不要h来管理,这样一来少了h的配置,二来不需要定义每个表对应的实体类,也算省了很多事情,在使用native sql的时候有一些需要注意的地方:
  Session s = sessionFactory.openSession();
		  
	       
			  String sql="select book.bookname,borr.borrowTime,borr.backTime,pub.pubname,bs.name  bookcasename,book.price from "
+"(select * from tb_borrow where ifback=0) "
+"as borr left join tb_bookinfo book on borr.bookid=book.id join tb_publishing pub "
+"on book.isbn=pub.isbn join tb_bookcase bs "
+" on book.bookcase=bs.id join tb_reader r on borr.readerid=r.id where r.barcode=?";
			  Query query=s.createSQLQuery(sql).addScalar("bookname", Hibernate.STRING) .addScalar("borrowTime", Hibernate.STRING).
					  addScalar("backTime", Hibernate.STRING).addScalar("pubname", Hibernate.STRING).
					  addScalar("bookcasename", Hibernate.STRING).addScalar("price", Hibernate.STRING);   
			  query.setParameter(0, barCode);
			   List list=null;	   
			   try{ 
				   list=query.list();	
			   s.close(); }
			  catch (Exception e)
			  {				  
				  
				  e.printStackTrace();
			  }
		
		return list;


1.  Session session = sessionFactory.openSession();session.createSQLQuery(sql);通过这种方式获得查询对象query。
2.  
  list=query.list();	得到的是一个数组列表(ArrayList),其中列表的每个元素都是object类型的数组,代表查询结果的一条记录,也就是说h会将sql查询出来的其中的每个字段都强制转换成Object类型,然后组成一个数组方到list里面去


3.单纯使用
s.createSQLQuery(sql)往往会报“找不到列”的错误,其实这是h对native sql支持的原因,因为Hibernate是通过使用ResultSetMetadata来判定返回的标量值的实际顺序和类型的,假若某个指定的类型没有被映射,或者不是你所预期的类型那么就会出现上述错误了,所以通过addScalar()明确指出返回什么列以及每个列的类型就可以避免上述错误了

最好你根据实际的类型将得到的object转换成实际的类型,就可以得到这些类型中保存的信息了。
  • 1
  • 2
  • 3
  • 4
  • 下一页

相关内容