最近在整合springsecurity,由于表间都是用的多对多,所以当要join取数据时,传统的ORM思想带来性能问题,HQL语句写的太大,所以就想采用传统的SQL.现记录如下,留做后用.
这里只留关键程序.其它的忽略.
/**根据手工创建的sql语句来查询,返回指定的class对象
* @param sqlQuery
* @param clazz
* @return
*/
public List<? extends BaseModel> findListBySQLQuery(String sqlQuery, Class<? extends BaseModel> clazz)
{
Query q= getSession().createSQLQuery(sqlQuery);
q.setResultTransformer(new CustomResultTransformer(clazz));
return q.list();
}
如果你的系统里没有BaseModel,将上面的去掉就是了.
CustomResultTransformer 是从一个同学的博客里抄来的.这里就不写出来了,大家可以在javaeye上搜索一下.
最后的效果就是,比如执行SELECT a.id, a.roleName FROM dbo.role a INNER JOIN groupRole c ON a.roleId = c.roleId INNER JOIN dbo.groups b ON c.groupID = b.groupID inner join dbo.groupUser d on b.groupId=d.groupID inner join dbo.users e on d.userid=e.userid WHERE (e.userName =?).然后我们有一个VO类userinfo,那么这个VO类里的id,roleName都会被set上值,其它的属性忽略.并且不报错.
人生从此就舒坦了.
当然,学好HQL才是我们的正途,这些歪门邪道的还是少用的好.
下面是最新的代码,解决了3个问题,
1.如果没有对应的set则不注入。以前是报错。
2.如果从数据库中取出的是空,也不注入。以前是报错。
3.如果从数据库中取出的值 类型不对,刚强制转换为setter需要的值。
/*
* (#)CustomResultTransformer.java 1.0 2010-6-21
*/
package com.framework.hibernate.util;
import java.lang.reflect.Field;
import java.util.List;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang.ArrayUtils;
import org.hibernate.HibernateException;
import org.hibernate.property.ChainedPropertyAccessor;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.property.Setter;
import org.hibernate.transform.ResultTransformer;
/**
* 本类的使用意义 2.public List<?> findObjectBySql(String queryString,Class<?> pojoClass){ 3. //使用SQL构造查询对象,此SQL是可以被JDBC接受的SQL,如SELECT * FROM XXX_TABLE 4. Query query =
* this.getSession().createSQLQuery(queryString); 5. //设置结果集转换器,这是本文重点所在 6. query.setResultTransformer(new CustomResultTransformer(pojoClass)); 7. //返回查询结果 8. return query.list();
* 自定义的数据库字库转换成POJO
*/
public class CustomResultTransformer implements ResultTransformer
{
private static final long serialVersionUID = 1L;
private final Class resultClass;
private Class[] clazz;
private Setter[] setters;
private final PropertyAccessor propertyAccessor;
public CustomResultTransformer ( Class resultClass )
{
if ( resultClass == null )
throw new IllegalArgumentException ( "resultClass cannot be null" );
this.resultClass = resultClass;
propertyAccessor = new ChainedPropertyAccessor ( new PropertyAccessor[] { PropertyAccessorFactory.getPropertyAccessor ( resultClass , null ),
PropertyAccessorFactory.getPropertyAccessor ( "field" ) } );
}
// 结果转换时,HIBERNATE调用此方法
public Object transformTuple ( Object[] tuple , String[] aliases )
{
Object result;
try
{
if ( setters == null )
{// 首先初始化,取得目标POJO类的所有SETTER方法
setters = new Setter[aliases.length];
clazz = new Class[aliases.length];
for ( int i = 0 ; i < aliases.length ; i++ )
{
String alias = aliases[i];
if ( alias != null )
{
// 我的逻辑主要是在getSetterByColumnName方法里面,其它都是HIBERNATE的另一个类中COPY的
// 这里填充所需要的SETTER方法
setters[i] = getSetterByColumnName ( alias , i );
}
}
}
result = resultClass.newInstance ( );
// 这里使用SETTER方法填充POJO对象
for ( int i = 0 ; i < aliases.length ; i++ )
{
if ( setters[i] != null && tuple[i] != null )
{
try
{
setters[i].set ( result , ConvertUtils.convert ( tuple[i] , clazz[i] ) , null );
} catch ( SecurityException e )
{
e.printStackTrace ( );
}
}
}
} catch ( InstantiationException e )
{
throw new HibernateException ( "Could not instantiate resultclass: " + resultClass.getName ( ) );
} catch ( IllegalAccessException e )
{
throw new HibernateException ( "Could not instantiate resultclass: " + resultClass.getName ( ) );
}
return result;
}
// 根据数据库字段名在POJO查找JAVA属性名,参数就是数据库字段名,如:USER_ID
private Setter getSetterByColumnName ( String alias , int index )
{
// 取得POJO所有属性名
Field[] fieldsSuperClass = resultClass.getSuperclass ( ).getDeclaredFields ( );
Field[] fieldsMine = resultClass.getDeclaredFields ( );
Field[] fields = (Field[]) ArrayUtils.addAll ( fieldsSuperClass , fieldsMine );
if ( fields == null || fields.length == 0 )
{
throw new RuntimeException ( "实体" + resultClass.getName ( ) + "不含任何属性" );
}
// 把字段名中所有的下杠去除
String proName = alias.replaceAll ( "_" , "" ).toLowerCase ( );
for ( Field field : fields )
{
if ( field.getName ( ).toLowerCase ( ).equals ( proName ) )
{
// 去除下杠的字段名如果和属性名对得上,就取这个SETTER方法
clazz[index] = field.getType ( );
return propertyAccessor.getSetter ( resultClass , field.getName ( ) );
}
}
//throw new RuntimeException("找不到数据库字段 :" + alias + " 对应的POJO属性或其getter方法,比如数据库字段为USER_ID或USERID,那么JAVA属性应为userId");
return null;
}
public List transformList ( List collection )
{
return collection;
}
}
分享到:
相关推荐
hibernate执行原生sql语句
hibernate中使用sql 而不是hql语句
Hibernate在Myeclipse下SQL语句演示,包含有HQL and Criteria语句的编写测试。
让hibernate输出sql语句参数配置.doc
模仿Hibernate生产SQL语句,使用Java反射
虽然在hibernate中有show_sql选项,但是显示出来的语句大多类似 select * from xxx where value=? 但是有时候我们需要得到完整的SQL语句,怎么办呢?使用P6SPY就可以完成这个任务
NULL 博文链接:https://ynp.iteye.com/blog/2007053
主要介绍了在Java的Hibernate框架中使用SQL语句的方法,Hibernate是Java的SSH三大web开发框架之一,需要的朋友可以参考下
hibernate将本地SQL查询结果封装成对象。如进行复杂的统计等本地sql语句查询后,直接放到对象里了,而不会再使用Object进行强转
spring_Framework+经典SQL语句大全+Hibernate中文API
hibernate执行sql文件中的sql并返回相应结果类似Mybatis功能
使用本地sql语句查询后,无需再使用Object对查询结果进行强制转换,而是直接将查询结果放到实体Bean里了。 PS: 其实只有一版,这里只所以叫最终版是因为该附件我上传了好几天传不上去,到最后报告说‘资源已经存在...
hibernate实现动态SQL查询,通过XML配置SQL,FREEMARKER 解析,生成要执行的SQL
上传的资料都是非常经典的,这也是我学习过程中的心得,希望大家能给我指点,也希望大家多上传资料共同学习。千万不要传空文件夹。。。
hibernate 中HQL语句查询学习笔记
hibernate-HQL语句大全
Hibernate中的查询方法若HQL,详细讲解HQL与使用的具体例子
基于sql语句的分页,效率更高,此jar包包含常用分页格式 使用方法在jboss5的博客中
六步骤轻松完成Hibernate中生成VO.xml(doc)
NULL 博文链接:https://javatozhang.iteye.com/blog/2045875