`
zhaobohao
  • 浏览: 21376 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

在Hibernate中执行传统的sql语句,并将结果Set到VO中

    博客分类:
  • JAVA
阅读更多
最近在整合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;
	}
	
}


分享到:
评论

相关推荐

    值对象转换成SQL语句

    "值对象转换成SQL语句"的主题涉及到了如何将程序中的对象模型直接映射到SQL查询,这通常被称为对象关系映射(ORM)。ORM是一种编程技术,它允许开发者使用面向对象的方式来操作数据库,而无需直接编写SQL语句,降低...

    Hibernate 简单使用 hibernate, ppt

    在项目中添加Hibernate支持,设置`show_sql=true`以便查看生成的SQL语句。通过IDE的工具,可以方便地进行对象-关系映射(ORM)配置,并进行测试验证。 最后,我们将简要讨论一对一的关系映射。例如,一个中国公民...

    hibernate的_映射、三态、脏数据、Session缓存

    当Session关闭或事务提交时,Hibernate会比较当前对象的状态与最后一次刷新时的状态,如果发现有变化,则会执行必要的SQL语句来同步这些变化到数据库。 #### 四、Session缓存 **Session缓存**是指在一个Session...

    Hibernate 开发学习指导书

    首先需要下载Ant软件包,并将其bin目录添加到系统的PATH环境变量中。 2. **下载Hibernate相关软件包**: - Hibernate: 主要的ORM框架。 - Hibernate-Extension: 扩展Hibernate功能的插件。 - Middlegen-Hibernate:...

    hibernate配置要点详谈

    - 对于`save`操作,如果对象已经与`Session`关联,则无需额外操作,因为`Session.flush`过程中,Hibernate会遍历实体容器中的对象,检测并执行相应的更新语句。 通过以上详细的解析,我们可以看到Hibernate提供了...

    Hibernate 课件 pdf

    - **对象/关系映射**: Hibernate 将 Java 对象映射到关系型数据库的表中,并将对象实例的状态存储到数据库表的行中。这种映射机制允许开发者以面向对象的方式来操作数据库。 - **查询和数据检索**: Hibernate 提供了...

    Hibernate_DEV_GUIDE.pdf

    为了使用Hibernate,你需要下载Ant,并将其bin目录添加到系统的PATH环境变量中。 - 下载地址: [Apache Ant](https://ant.apache.org/) 2. **下载Hibernate**: Hibernate提供了多种组件和扩展,确保下载最新的...

    JSP教程之与数据库通信

    `Statement`用于执行静态SQL语句,而`PreparedStatement`用于执行预编译的SQL语句,可以防止SQL注入攻击。 例如,使用`PreparedStatement`插入数据: ```java String sql = "INSERT INTO mytable (column1, column...

    CatFramework持久层

    性能:CatFramework实现了VO的属性的版本管理,只有发生变化的字段才更新数据库,比如:User表有 Id ,Name ,Sex三个字段,用户在修改时,只修改了Name,那么生成的sql语句只有update User set Name=? where Id=? 而...

    HQL.pdf数据查询语句

    在上述代码中,`from User`是HQL语句,它将会返回User实体对应的数据库表中的所有记录。 另外,也可以指定类的完全限定名来进行查询: ```java Query query = session.createQuery("from com.vo.User"); ``` 注意,...

    Dao设计模式

    实现类中会包含具体的数据访问逻辑,比如与数据库表的映射关系,以及使用JDBC或ORM框架如Hibernate来执行具体的数据库操作。 6. 类与数据表的映射关系:在数据访问层的实现中,常常需要定义一些数据传输对象(DTOs...

    java代码规范要求(公司用-补充版).pdf

    15. 公共方法:将重复使用的代码提取到公共类或工具类中。 16. 无效代码处理:删除或注释掉不再使用的代码。 17. 代码测试:在提交前完成测试,确保不引发其他模块错误。 18. 配置文档:遵循规范格式,增加注释,...

    牛人的spring学习笔记,非常适合初学者

    3. **引入Spring的JAR包**:根据Spring版本的不同,需要下载相应的JAR包,并将其添加到项目的类路径中。 4. **测试代码**:编写测试代码来验证Spring环境是否正确配置,通常会涉及Bean的获取和依赖关系的检查。 5. *...

    spring2.5 学习笔记

    - **使用**:演示如何在实际应用中注入并使用数据源。 #### 第十课:Spring 整合 Hibernate - **配置 SessionFactory**: - **XML 形式**:使用 `&lt;bean&gt;` 标签来配置 Hibernate 的 `SessionFactory`。 - **...

Global site tag (gtag.js) - Google Analytics