JAVA

人生若只如初见,何事秋风悲画扇。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  50 随笔 :: 25 文章 :: 157 评论 :: 0 Trackbacks

  以下是我在hibernate查询(通过Spring)中碰到的一个小问题及其解决方法,简单但实用,希望也有益于各同友。 

  在用hibernate查询中假如用到一个带中文的参数,如:

String hql  =   " from Customer user where 1=1 and userr.mc like '%惠止南国%' " ;
Session session 
=  getHibernateTemplate().getSessionFactory().openSession(); // Spring
Transaction tx  =  session.beginTransaction();
Query qry 
=  session.createQuery(sql);
List returnList 
=  qry.list();
tx.commit();
session.close();


  在执行过程中在eclpise的console台中可以看到hibernate经过底层将其译成SQL后成了:

  select ... from Customer user  where 1=1 and userr.hh like '%??????%'

  的样子。我试过将其以不同的方式编码,可是都没有将其最终以正确的结果返回。暂且不谈此方法应该如何写,我主要是想说通过用另外一种查询方法:在HQL中绑定参数预编译机制来解决这个乱码问题。

  参数绑定机制有如下优点:
  a 安全感,防止恶意用户非法调用DB的存储过程
  b 利用底层数据库编译SQL的功能,提高数据库查询性能。预编译是指底层数据库系统只能编译SQL语句一次,把编译出来的可执行代码保存在缓存中,如果有多次执行相同的SQL语句,不需要重新编译,只要从缓存中读取即可。

  将上面的执行过程改成如下:

List params  =   new  ArrayList();
String hql 
=   " from Customer user where 1=1 and userr.mc like ? " ;
params.add(
" '% "   +  form.get( " zdmlmc " ).toString()  +   " %' " );
Object[] objs 
=  params.toArray();
Session session 
=  getHibernateTemplate().getSessionFactory().openSession();
Transaction tx 
=  session.beginTransaction();
Query qry 
=  session.createQuery(sql);
if  (objs  ==   null //  判断是否确认参数名称
{
 
if (objs.length > 0 )
  
for  ( int  i  =   0 ; i  <  objs.length; i ++
   qry.setParameter(i, objs[i]);
}

List returnList 
=  qry.list();
tx.commit();
session.close();


  这样就可以看到在console中最后所执行的SQL:

  select ... from Customer user  where 1=1 and userr.mc like '%惠止南国%'

  在上面中有这样的语句:

  qry.setParameter(i, objs[i]);

  这是属于按参数位置绑定中的绑定任意的参数类型。

  org.hibernate.Query的参数绑定形式可以分为

  1 按参数位置绑定

  2 按参数位置绑定

  Query绑定参数类型可以分为:

  1 参数与持久化类实体绑定

Customer cus  =   new  Customer();
  
// 省略其它初始化
  
// 以下是按参数位置绑定
  query.setEntity( " pa_name " ,customer);
  
//  or 
       
// 按参数位置绑定
  query.setEntity(index_location,customer); // index_location是其在HQL中的下标位置,从0开始


  2 绑定任意类型参数

  上面中的qry.setParameter(...)就是这种类型,我们qry.setParameter(i, objs[i]);中是省略了第三个参数即Hibernate映射类型,如:

  qry.setParameter(i, objs[i],Hibernate.STRING);

  对于有些参数,Hibernate能根据参数值的java类型推断出对应的映射类型,此时不再要在setParameter()中显式指定映射类型。如上

  3 将命名参数与一个对象属性绑定

  setProperties()方法

  个人觉得这个跟ORM技术的ibatis中的SQLMAP有些许相似。它是用setProperties()方法。如:

String hql  =   " from Customer user where 1=1 and userr.mc like :sna " ;
Customer cus 
=   new  Customer();
cus.setMc(
" 惠止南国 " );
Session session 
=  getHibernateTemplate().getSessionFactory().openSession();
Transaction tx 
=  session.beginTransaction();
List returnList 
=  session.createQuery(sql).setProperties(cus).list();
tx.commit();
session.close();

Attention:对于日期型数据不能用setProperties()方法通过实体来绑定。


 

posted on 2006-10-13 11:44 Jkallen 阅读(3871) 评论(2)  编辑  收藏 所属分类: 其它开源

评论

# re: 在HQL中绕过中文乱码查询 2007-03-07 11:43 小小
如果hql是动态的呢?有没有什么好的解决办法?  回复  更多评论
  

# re: 在HQL中绕过中文乱码查询[未登录] 2012-06-05 21:21 齐齐
锿?  \ D e v i c e \ H a r d d i s k V o l u m e 2 \ S y s t e m V o l u m e I n f o r m a t i o n \ _ r e s t o r e { 5 0 6 7 A 8 1 3 - E 8 E A - 4 C 9 C - 8 1 9 E - 3 6 6 E 5 C E D 6 4 7 1 } \ R P 3 8 \ c h a n g e . l o g `  锿珋 9U   \ _ 6 4 1 1 2 5 _ ` ?  锿    :U   \ _ 6 4 1 1 2 5 _    € 0 L   &v/?+F倠??   &v/?+F倠?            $    &v/?+F倠??        !     !     !  _ 6 4 1 1 2 5 _ ?   回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: