简单修改Hibernate源码,增加使用原生SQL查询时动态addEntity和addScalar功能

简单修改Hibernate源码,增加使用原生SQL查询时动态addEntityaddScalar功能

@for&ever 2009-9-5

相关文章,参考:

http://blog.csdn.net/forandever/archive/2009/09/04/4520787.aspx

 

环境:

Hibernate3.3

 

在使用 Hibernate进行原生SQL查询的时候,必须要在createSQLQuery之后紧跟 addEntityaddScalar才可以,要想在离开初始的 createSQLQuery之后进行这个操作是不行的。

例如:

如下使用是可以的:

session.createSQLQuery(sql).addEntity("entityXXXX", XXXX.class).addScalar("strYYYY", Hibernate.STRING);

或者

session.createSQLQuery(sql).addEntity(XXXX.class).addScalar(Hibernate.STRING);

 

但如果在拆分开之后,就不能用了。例如:

Query q = session.createSQLQuery(sql)

q.addEntity(XXXX.class).addScalar(Hibernate.STRING); // XXXX 出错。 Eclipse下会提示错误。

这是Hibernate里按着实际的应用环境场景的设置,是没问题的。

 

但是,现在有这样的一个使用场景:

构建一个泛型的Dao,里面要能够根据多个参数动态的设置 addEntity addScalar等。

如下的情形:

要实现一个如下的方法:

public List getListBySQL(String sql,String returnAliases[], Class returnClasses[]);

 

该方法的功能是,根据原生的sql查找到结果。sql 中设置的别名Aliases 可以动态的设置Entity

sql是传入的原生SQLreturnAliases[] 是别名的数组,returnClasses是要动态设置的Entity

sql不固定时,可以通过这个方法进行动态设置。

 

可能的实际例子:

如下的SQL语句:

select {bbbb.*}, {aaaa.*} from question {bbbb} left join answer {aaaa}  on {aaaa}.id={bbbb}.ansId

 

实体类 Question Answer需要动态设置。

 

如下的查询是可以的:

Query q = session.createSQLQuery(sql).addEntity(Question.class).addEntity(Answer.class);

但是如果每次的 sql语句参数都动态变化,并且要操作 addEntity addScalar的数目也不确定的时候,就需要修改Hibernate的源码。

 

具体修改方法为:

 

1、修改接口 org.hibernate.Session,增加方法:

 

public Query createSQLQuery(String sql, String returnAliases[], Object returnObjectes[]);

这里的第三个参数 Object returnObjectes[] 类型是 Object,就是为了适应 Entity Scalar的不同。

 

2、修改 org.hibernate.impl.AbstractSessionImpl,增加实现:

 

         public Query createSQLQuery(String sql, String returnAliases[], Object returnObjectes[]){

                   errorIfClosed();

                   SQLQuery query = createSQLQuery(sql);

                   for(int i = 0; i < returnAliases.length; i ++){

                            if(returnAliases[i].startsWith("__")){

                                     query.addScalar(returnAliases[i].substring(2), (Type) returnObjectes[i]);

                            }else{

                                     query.addEntity(returnAliases[i], (Class)returnObjectes[i]);

                            }

                   }

                   return query;

         }

 

当然,如果实现写在 SessionImpl 里面也可以。

 

一点小说明:

if(returnAliases[i].startsWith("__"))

这里是为了通过 Aliases 的值来判断是应该调用 addScalar 还是调用addEntity

因此,要注意 returnAliases 的顺序和要设置的 returnObjectes 的顺序要对应才行。

 

 

接下来,就可以使用上面提到的 getListBySQL 方法,进行动态设置,参数如下:

 

String returnAliases[] = new String[]{ "bbbb", "aaaa"};

// Class returnClasses[] = new Class[] { Question.class, Answer.class}; // 使用下一行的 Object类型,兼容 Scalar Entity

Object returnObjectes[] = new Object[] { Question.class, Answer.class};

 

修改一下 getListBySQL ,实现如下:

public List getListBySQL(String sql,String returnAliases[], Object returnObjectes[]){

         Query q = session.createSQLQuery(sql , returnAliases, returnObjectes);

         q.setParameter(...)

         .........

}

 

经过查询后,就可以得到  Question Answer 组合一起的 List

 

这样就实现了根据传入的不同的SQL动态的设置查出的实体或者类型。

 

注:

Hibernate自身带有方法

public Query createSQLQuery(String sql, String returnAliases[], Class returnClasses[])

和方法

public Query createSQLQuery(String sql, String returnAlias, Class returnClass)

的实现。

 

但是它没有提供使用它们的接口。如果只是简单的使用以上的两个方法,也可以直接在接口的定义中加入以上两个方法。

 

 

但本文实现的方法,可以覆盖包含以上两个方法的功能。

 

@forandever 2009-9-5

 

 



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值