hibernate将本地SQL查询结果封装成对象
2012-05-08 20:27
471 查看
hibernate将本地SQL查询结果封装成对象
不知道大家有没有碰过这种情况,迫于很多情况只能用native SQL来查询(如:复杂统计等),然而使用native查询后,结果会被放到object里,要想拿到对应的数据只能由object来强制转换,真的好烦人。因为工作原因,笔者(sourcefour)正在做大量的统计而每次都要进行强制转换,这其实是很麻烦的。我在想如果native
SQL查询结果也能够封装对象就好了,于是狠狠的查看了hibernate文档,终于发现了一件令人高兴的事情——native SQL查询的结果也是可以封装成对象滴(具体请看hibernate文档【第16章】)。这种情况不得不高兴啊,于是动手做实验,结果还是令人兴奋的----成功了(^_^)于是将实验结果整理以备以后用。
总的来说,使用本地SQL查询出来的结果也可以直接放到Bean里,如以下情况(只能想到这么多):
直接使用本地(native)SQL查询(废话,说的不就是使用native sql嘛^_^)
我例子中的Bean如下:
亮点在代码中注释的两句。其中AddScalar.addSclar是自己写的,具体请看代码:
所有的准备工作都做好了,那么就看我们的具体的DAO操作及单元测试。
具体DAO:
说明:sql语句中的别名就是我们Bean中的字段
Junit测试代码:
运行结果:
到了这里应该说一切OK鸟。
完整的文档,SQL,工程下载地址:CSDN下载
说明:本说明是关于资源附件的,在资源中附件名称叫做 ‘hibernate将本地SQL查询结果封装成对象(最终)’,其实只有一版,这里只所以叫最终版是因为该附件我上传了好几天传不上去,到最后报告说‘资源已经存在’,但我确实没有看到附件。所以没办法只能改个名字了…………
。(V_V)。
PS:
Jdk1.6+,
Junit4
工程编码:utf-8
转载请注明作者与出处
不知道大家有没有碰过这种情况,迫于很多情况只能用native SQL来查询(如:复杂统计等),然而使用native查询后,结果会被放到object里,要想拿到对应的数据只能由object来强制转换,真的好烦人。因为工作原因,笔者(sourcefour)正在做大量的统计而每次都要进行强制转换,这其实是很麻烦的。我在想如果native
SQL查询结果也能够封装对象就好了,于是狠狠的查看了hibernate文档,终于发现了一件令人高兴的事情——native SQL查询的结果也是可以封装成对象滴(具体请看hibernate文档【第16章】)。这种情况不得不高兴啊,于是动手做实验,结果还是令人兴奋的----成功了(^_^)于是将实验结果整理以备以后用。
1. 适用对象
可以将以下几种查询结果用Bean封装起来。通俗点说就是查询出来之后就直接将内容放到了Bean实体里。总的来说,使用本地SQL查询出来的结果也可以直接放到Bean里,如以下情况(只能想到这么多):
直接使用本地(native)SQL查询(废话,说的不就是使用native sql嘛^_^)
2. 具体实现步骤
2.1. 实体Bean
实体Bean的写法和对象Bean的写法是一样的。区别在于该实体Bean是不需要做Hibernate映射的。我例子中的Bean如下:
package com.sourcefour.bean; /** * 这里说明一下,该Bean中的field没必要一定是数据表中的field。 * 而应该是DAO中要查询字段的别名,具体请看例子NativeSqlDao, * 我想你会明白的 * * @author sourcefour */ public class NativeSqlBean { private double maxMos; private double minMos; private double avgMos; private int userCount; private String name; public double getMaxMos() { return maxMos; } public void setMaxMos(double maxMos) { this.maxMos = maxMos; } public double getMinMos() { return minMos; } public void setMinMos(double minMos) { this.minMos = minMos; } public double getAvgMos() { return avgMos; } public void setAvgMos(double avgMos) { this.avgMos = avgMos; } public int getUserCount() { return userCount; } public void setUserCount(int userCount) { this.userCount = userCount; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2.2. Dao操作
直接上代码:package com.sourcefour.dao.base; import java.sql.SQLException; import java.util.List; import javax.annotation.Resource; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.transform.Transformers; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * @author sourcefour */ @SuppressWarnings("unchecked") @Transactional public abstract class BaseDaoSupport<T> extends HibernateDaoSupport { @Resource(name = "sessionFactory") public void setSuperSessionFactory(SessionFactory sessionFactory) { super.setSessionFactory(sessionFactory); } /** * 使用sql语句进行分页查询 * * @param sql * sql语句 * @param values * 参数 * @param offSet * 第一条记录序号 >-1 * @param pageSize * 每页要显示的记录数 >0 * @param beanClass * 将查询结果转换为<tt>T</tt>对象 * @param fieldList * 查询Bean的成员变量名称 */ @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) public List<T> list(final String sql, final Object[] values, final int offSet, final int pageSize, final Class<T> beanClass, final List<String> fieldList) { List<T> list = getHibernateTemplate().executeFind(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { SQLQuery sqlQuery = session.createSQLQuery(sql); // 添加要查询字段的标量 AddScalar.addSclar(sqlQuery, beanClass, fieldList); Query query = sqlQuery; // 转换查询结果为T if (beanClass != null) { query.setResultTransformer(Transformers.aliasToBean(beanClass)); } if ((values != null) && values.length > 0) { int i = 0; for (Object obj : values) { query.setParameter(i++, obj); } } if (offSet > -1) { query.setFirstResult(offSet); } if (pageSize > 0) { query.setMaxResults(pageSize); } return query.list(); } }); return list; } }
亮点在代码中注释的两句。其中AddScalar.addSclar是自己写的,具体请看代码:
package com.sourcefour.dao.base; import java.lang.reflect.Field; import java.util.Date; import java.util.List; import org.hibernate.Hibernate; import org.hibernate.SQLQuery; /** * @author sourcefour */ public class AddScalar { /** * 将field type 和 Hibernate的类型进行了对应。这里其实不是多余的,如果不进行一定的对应可能会有问题。 * 问题有两个: * 1. 在oracle中我们可能把一些字段设为NUMBER(%),而在Bean中的字段定的是long。那么查询时可能会报: * java.math.BeigDecimal不能转换成long等错误 * 2. 如果不这样写的话,可能Bean中的field就得是大写的,如:name就得写成NAME,userCount就得写成USERCOUNT * 这样是不是很扯(V_V) * * @param <T> * @param sqlQuery * SQLQuery * @param clazz * T.class * @param fieldList * 要查询的成员变量名称 */ public static <T> void addSclar(SQLQuery sqlQuery, Class<T> clazz, List<String> fieldList) { if (clazz == null) { throw new NullPointerException("[clazz] could not be null!"); } if ((fieldList != null) && (fieldList.size() > 0)) { Field[] fields = clazz.getDeclaredFields(); for (String fieldName : fieldList) { for (Field field : fields) { if (fieldName.equals(field.getName())) { if ((field.getType() == long.class) || (field.getType() == Long.class)) { sqlQuery.addScalar(field.getName(), Hibernate.LONG); } else if ((field.getType() == int.class) || (field.getType() == Integer.class)) { sqlQuery.addScalar(field.getName(), Hibernate.INTEGER); } else if ((field.getType() == char.class) || (field.getType() == Character.class)) { sqlQuery.addScalar(field.getName(), Hibernate.CHARACTER); } else if ((field.getType() == short.class) || (field.getType() == Short.class)) { sqlQuery.addScalar(field.getName(), Hibernate.SHORT); } else if ((field.getType() == double.class) || (field.getType() == Double.class)) { sqlQuery.addScalar(field.getName(), Hibernate.DOUBLE); } else if ((field.getType() == float.class) || (field.getType() == Float.class)) { sqlQuery.addScalar(field.getName(), Hibernate.FLOAT); } else if ((field.getType() == boolean.class) || (field.getType() == Boolean.class)) { sqlQuery.addScalar(field.getName(), Hibernate.BOOLEAN); } else if (field.getType() == String.class) { sqlQuery.addScalar(field.getName(), Hibernate.STRING); } else if (field.getType() == Date.class) { sqlQuery.addScalar(field.getName(), Hibernate.TIMESTAMP); } } } } } } }
所有的准备工作都做好了,那么就看我们的具体的DAO操作及单元测试。
具体DAO:
package com.sourcefour.dao; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Repository; import com.sourcefour.bean.NativeSqlBean; import com.sourcefour.dao.base.BaseDaoSupport; /** * @author sourcefour */ @Repository public class NativeSqlDao extends BaseDaoSupport<NativeSqlBean> { public List<NativeSqlBean> listAll(int offSet, int pageSize) { String sql = "SELECT MAX(t.mos) maxMos, MIN(t.mos) minMos, AVG(t.mos) avgMos, COUNT(t.id) userCount FROM t_native_sql t"; List<String> fieldList = new ArrayList<String>(); fieldList.add("maxMos"); fieldList.add("minMos"); fieldList.add("avgMos"); fieldList.add("userCount"); return super.list(sql, new Object[] {}, offSet, pageSize, NativeSqlBean.class, fieldList); } }
说明:sql语句中的别名就是我们Bean中的字段
Junit测试代码:
package com.sourcefour.test.dao; import java.util.List; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.sourcefour.bean.NativeSqlBean; import com.sourcefour.dao.NativeSqlDao; /** * @author sourcefour */ public class NativeSqlDaoTest { private static NativeSqlDao nativeSqlDao; private static ApplicationContext applicationContext; @BeforeClass public static void setUp() { applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); nativeSqlDao = (NativeSqlDao) applicationContext.getBean("nativeSqlDao"); } @Test public void testListIntInt() { List<NativeSqlBean> list = nativeSqlDao.listAll(-1, -1); Assert.assertNotNull(list); for (NativeSqlBean nativeSqlBean : list) { System.out.println("maxMos: " + nativeSqlBean.getMaxMos()); } } }
运行结果:
到了这里应该说一切OK鸟。
完整的文档,SQL,工程下载地址:CSDN下载
说明:本说明是关于资源附件的,在资源中附件名称叫做 ‘hibernate将本地SQL查询结果封装成对象(最终)’,其实只有一版,这里只所以叫最终版是因为该附件我上传了好几天传不上去,到最后报告说‘资源已经存在’,但我确实没有看到附件。所以没办法只能改个名字了…………
。(V_V)。
PS:
Jdk1.6+,
Junit4
工程编码:utf-8
转载请注明作者与出处
相关文章推荐
- hibernate将本地SQL查询结果封装成对象
- hibernate将本地SQL查询结果封装成对象
- 从Object对象中封装了其它对象,怎样取出呢?(Hibernate查询结果处理)
- Hibernate查询,返回new对象(注意这个新定义的类要有构造函数),使用sql带条件分页查询并且把结果显示到一个对象的集里面的解决方案
- Hibernate查询,返回new对象(注意这个新定义的类要有构造函数),使用sql带条件分页查询并且把结果显示到一个对象的集里面的解决方案
- hibernate的sql多表查询结果组装为对象
- 解决Hibernate原生SQL映射问题 - SQL查询出来的结果映射为值对象
- Hibernate 自定义查询sql 并使用自定义对象接收查询结果
- Hibernate中使用sql查询结果后再封装成实体类的问题
- Hibernate查询之SQL查询,查询结果用new新对象的方式接受,hql查询,通过SQL查询的结果返回到一个实体中,查询不同表中内容,并将查到的不同表中的内容放到List中
- Hibernate查询之SQL查询,查询结果用new新对象的方式接受,hql查询,通过SQL查询的结果返回到一个实体中,查询不同表中内容,并将查到的不同表中的内容放到List中
- hibernate 使用sql 查询利用setResultTransformer查询出封装好的VO对象
- 关于hibernate如何把原生sql查出的结果转化为对象
- Hibernate中用纯SQL查询,并通过hibernate分页返回List<对象>
- Hibernate学习之QBC和本地SQL查询
- Hibernate本地SQL查询
- Hibernate查询条件封装对象Expression介绍
- hibernate+mysql中文查询不出结果,其他查询正常,SQL语句也正常
- 利用反射技术将查询结果封装为对象
- Hibernate 命名查询、本地SQL、自定义SQL