hibernate 的createSQLQuery的几种用法(转)


实际开发存在的问题

上面的操作具体对于实体的映射,可能是存在的实体映射(数据库总存在的表)

我现在遇到的情况是根据sql查询当前一些字段并且分装到一个非持久化的对象例如

String sql="select SUM(t.PRODUCT_QUALITY)AS countQuality,COUNT(t.PRODUCT_QUALITY) AS countNumbe from mms_assess_detail t where t.DELIVERY_ID='"+deliveryId.trim()+"' and t.product_quality <>0 AND t.product_quality IS NOT NULL";

Query query =this.getSessionFactory().getCurrentSession().createSQLQuery(sql).addScalar( "countQuality" , Hibernate.LONG).addScalar( "countNumbe" , Hibernate.LONG).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);

Query query1 =this.getSessionFactory().getCurrentSession().createSQLQuery(sql).addScalar( "countQuality" , Hibernate.LONG).addScalar( "countNumbe" , Hibernate.LONG).setResultTransformer(Transformers.aliasToBean(Test.class));

Query query2 =this.getSessionFactory().getCurrentSession().createSQLQuery(sql).addScalar( "countQuality" , Hibernate.LONG).addScalar( "countNumbe" , Hibernate.LONG).setResultTransformer(Transformers.TO_LIST);

 List> list1=query.list();返回值是一个List的map集合key值就是别名,value就是查询出来的值

List list2=query1.list(); 返回的直接就是实体对应的list,注意Test对象是非持久话对象。

list list3=  query2 .list();返回的是纯list这个对于查询一个字段的时候比较有用。




使用SQLQuery
对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取这个接口。最简单的情况下,我们可以采用以下形式:

List cats= sess.createSQLQuery(" select * from cats " ).addEntity(Cat. class).list();

这个查询指定了:

SQL查询字符串

查询返回的实体

这里,结果集字段名被假设为与映射文件中指明的字段名相同。对于连接了多个表的查询,这就可能造成问题,因为可能在多个表中出现同样名字的字段。下面的方法就可以避免字段名重复的问题:

List cats= sess.createSQLQuery(" select {cat.*} from cats cat " ).addEntity( " cat " , Cat. class).list();

这个查询指定了:

SQL查询语句,它带一个占位符,可以让Hibernate使用字段的别名.

查询返回的实体,和它的SQL表的别名.

addEntity()方法将SQL表的别名和实体类联系起来,并且确定查询结果集的形态。

addJoin()方法可以被用于载入其他的实体和集合的关联.

List cats= sess.createSQLQuery(
" select {cat.*}, {kitten.*} from cats cat, cats kitten wherekitten.mother = cat.id " )
.addEntity( " cat " , Cat. class )
.addJoin( " kitten " , " cat.kittens " )
.list();

原生的SQL查询可能返回一个简单的标量值或者一个标量和实体的结合体。

Doublemax = (Double) sess.createSQLQuery(" select max(cat.weight) as maxWeight from cats cat ")
.addScalar( " maxWeight " , Hibernate.DOUBLE);
.uniqueResult();

除此之外,你还可以在你的hbm文件中描述结果集映射信息,在查询中使用。

List cats= sess.createSQLQuery(
" select {cat.*}, {kitten.*} from cats cat, cats kitten wherekitten.mother = cat.id " )
.setResultSetMapping( " catAndKitten " )
.list();

命名SQL查询
可以在映射文档中定义查询的名字,然后就可以象调用一个命名的HQL查询一样直接调用命名SQL查询.在这种情况下,我们不需要调用addEntity()方法.

 
< return alias = " person " class = " eg.Person "/> 
Select person.NAME AS {person.name},person.AGE AS{person.age},person.SEX AS {person.sex} FROM PERSON person Whereperson.NAME LIKE :namePattern
List people= sess.getNamedQuery( " persons " ).setString( " namePattern " ,namePattern)
.setMaxResults( 50 )
.list();

----------------------------------------------

原来的查询语句:

String sql = "select a.* from tb_doc_catalog a where a.cat_codelike '"+catCode+"%'";
Session session = this.getSession();
try {
List catNameList = session.createSQLQuery(sql).list();
return catNameList ;
} finally {
releaseSession(session); //释放session
}

分析:原来是查询出来的字段并不能自动转换为bean对象。

解决思路一(采用hql查询):

String sql = "select a from DocCatalogInfo a where a.catCode like'"+catCode+"%'";
List catNameList =getHibernateTemplate().find(sql);
return catNameList ;
ok,测试一下发现没问题,看来还是因为用原生sql查询的原因,网上搜一下:createsqlQuery返回对象,看到一篇文章才觉悟到:

解决思路二(采用原生sql查询):

String sql = "select a.* from tb_doc_catalog a where a.cat_codelike '"+catCode+"%'";
Session session = this.getSession();
try {
List catNameList =session.createSQLQuery(sql).addEntity(DocCatalogInfo.class).list();
return catNameList ;
} finally {
releaseSession(session); //释放session
}

又ok了。

该篇文章也贴上来:

hibernate 中createQuery与createSQLQuery两者区别是:
前者用的hql语句进行查询,后者可以用sql语句查询
前者以hibernate生成的Bean为对象装入list返回
后者则是以对象数组进行存储
所以使用createSQLQuery有时候也想以hibernate生成的Bean为对象装入list返回,就不是很方便
突然发现createSQLQuery有这样一个方法可以直接转换对象
Query query =session.createSQLQuery(sql).addEntity(XXXXXXX.class);
XXXXXXX 代表以hibernate生成的Bean的对象,也就是数据表映射出的Bean。
呵呵以后多注意,还是时不时的要看看hibernate各个对象方法的使用。

还有另外一个相关的小细节应注意:
比如有这样一个po
PO: User.class
properties: userId,userName
DDL: create table tuser (userid varchar(10),usernamevarchar(20));
当执行:
session.createQuery("from User u").list()时生成的SQL:
  select userid,username from tuser;
当执行:

session.createQuery("from User u").iterator()时生成的SQL:
  
select userid from tuser;
  
可以看出list()一次将数据从数据库中读出直接填充到List中
  
iterator()将数据的主键从数据库中读出,当循环这个Iterator时才添加执行:
  
select userid,username from user where userid=?;把数据读出。
在不同的应用范围使用不同的方法,具体在hibernate应用中应当注意。

---------------------------------------------------------------------------------------------------

用法一(返回数值):
ISQLQuery query = session.CreateSQLQuery("SELECT COUNT(Id) AS CFROM Cake").AddScalar("C", NHibernateUtil.Int32);
int c = Convert.ToInt32(query.UniqueResult());
或int c =query.UniqueResult;//使用此方法发现sql执行了两次,故不推荐使用。

 用法二(返回对象实体):
ISQLQuery query = session.CreateSQLQuery("select * from cakec").AddEntity("CAKE.DataTransfer.Entities.Cake");
或ISQLQuery query = session.CreateSQLQuery("select * from cakec").AddEntity("c","CAKE.DataTransfer.Entities.Cake");
或ISQLQuery query = session.CreateSQLQuery("select * from cakec").AddEntity(typeof(Cake));
或ISQLQuery query = session.CreateSQLQuery("select * from cakec").AddEntity("c", typeof(Cake));
或ISQLQuery query = session.CreateSQLQuery("select * from cakec").AddEntity("c", typeof(Cake), LockMode.Write);

IList c =query.List();

用法三(连表查询):
ISQLQuery query = session.CreateSQLQuery("select cs.* from cake cjoin CakeSize cs on cs.CakeId=c.Id")
.AddEntity("cs", typeof(CakeSize));
IList cs =query.List();

以上是一种常见的用法,通过该例子,相信大家心里也已经有个数了,也应该知道怎么操作这个sql了:)

但是过程中难免会遇到些问题,比如:

实例二(问题说明):

我需要执行例如这条sql语句:

select CreateTime,Address,Password, (case when EmailType = 0 then'Gmail' when EmailType = 1 then 'Yahoo' when EmailType = 2 then'Hotmail' else 'Other' end) as EmailType fromMailInfo

1. 如果使用session.CreateQuery方法执行的话,你可能会遇到这样的错误:

错误:undefined alias or unknown mapping
ISession session =DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (casewhen EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo'when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailTypefrom MailInfo where status=0 Order by CreateTimedesc";
IQuery query = session.CreateQuery(queryString;
IList lst = query.List();

2. 使用CreateSQLQuery方法执行:

错误:Return types of SQL query were not specified...
ISession session =DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (casewhen EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo'when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailTypefrom MailInfo where status=0 Order by CreateTimedesc";
ISQLQuery query =session.CreateSQLQuery(queryString);
IList lst = query.List();

3.使用CreateSQLQuery方法并指定返回字段值的类型,即使用AddScalar方法指定字段值类型:

错误:could not execute query...

ISession session =DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (casewhen EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo'when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailTypefrom MailInfo where status=0 Order by CreateTimedesc";
ISQLQuery query =session.CreateSQLQuery(queryString).AddScalar("CreateTime",NHibernateUtil.String)
.AddScalar("Address",NHibernateUtil.String)
.AddScalar("Password",NHibernateUtil.String)
.AddScalar("EmailType",NHibernateUtil.Int32);
IList lst = query.List();
ISession session =DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (casewhen EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo'when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailTypefrom MailInfo where status=0 Order by CreateTimedesc";
ISQLQuery query =session.CreateSQLQuery(queryString).AddScalar("CreateTime",NHibernateUtil.String)
.AddScalar("Address",NHibernateUtil.String)
.AddScalar("Password",NHibernateUtil.String)
.AddScalar("EmailType",NHibernateUtil.Int32);
IList lst = query.List();

注意:EmailType字段对应数据库的类型是int,这里我就误解为也应该映射为NHibernateUtil.Int32;

4. 解决问题:

把AddScalar方法的参数里一个属性改了一下:

ISession session =DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (casewhen EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo'when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailTypefrom MailInfo where status=0 Order by CreateTimedesc";
ISQLQuery query =session.CreateSQLQuery(queryString).AddScalar("CreateTime",NHibernateUtil.String)
.AddScalar("Address",NHibernateUtil.String)
.AddScalar("Password",NHibernateUtil.String)
.AddScalar("EmailType",NHibernateUtil.String);
IList lst = query.List();
ISession session =DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (casewhen EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo'when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailTypefrom MailInfo where status=0 Order by CreateTimedesc";
ISQLQuery query =session.CreateSQLQuery(queryString).AddScalar("CreateTime",NHibernateUtil.String)
.AddScalar("Address",NHibernateUtil.String)
.AddScalar("Password",NHibernateUtil.String)
.AddScalar("EmailType",NHibernateUtil.String);
IList lst = query.List();





你可能感兴趣的:(开发遇到的问题)