hibernate将本地SQL查询结果封装成对象

不知道大家有没有碰过这种情况,迫于很多情况只能用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如下:

  1. package com.sourcefour.bean;
  2. /**
  3. * 这里说明一下,该Bean中的field没必要一定是数据表中的field。
  4. * 而应该是DAO中要查询字段的别名,具体请看例子NativeSqlDao,
  5. * 我想你会明白的
  6. *
  7. * @author sourcefour
  8. */
  9. public class NativeSqlBean {
  10. private double maxMos;
  11. private double minMos;
  12. private double avgMos;
  13. private int userCount;
  14. private String name;
  15. public double getMaxMos() {
  16. return maxMos;
  17. }
  18. public void setMaxMos(double maxMos) {
  19. this.maxMos = maxMos;
  20. }
  21. public double getMinMos() {
  22. return minMos;
  23. }
  24. public void setMinMos(double minMos) {
  25. this.minMos = minMos;
  26. }
  27. public double getAvgMos() {
  28. return avgMos;
  29. }
  30. public void setAvgMos(double avgMos) {
  31. this.avgMos = avgMos;
  32. }
  33. public int getUserCount() {
  34. return userCount;
  35. }
  36. public void setUserCount(int userCount) {
  37. this.userCount = userCount;
  38. }
  39. public String getName() {
  40. return name;
  41. }
  42. public void setName(String name) {
  43. this.name = name;
  44. }
  45. }

2.2.  Dao操作

直接上代码:

  1. package com.sourcefour.dao.base;
  2. import java.sql.SQLException;
  3. import java.util.List;
  4. import javax.annotation.Resource;
  5. import org.hibernate.HibernateException;
  6. import org.hibernate.Query;
  7. import org.hibernate.SQLQuery;
  8. import org.hibernate.Session;
  9. import org.hibernate.SessionFactory;
  10. import org.hibernate.transform.Transformers;
  11. import org.springframework.orm.hibernate3.HibernateCallback;
  12. import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
  13. import org.springframework.transaction.annotation.Propagation;
  14. import org.springframework.transaction.annotation.Transactional;
  15. /**
  16. * @author sourcefour
  17. */
  18. @SuppressWarnings("unchecked")
  19. @Transactional
  20. public abstract class BaseDaoSupport<T> extends HibernateDaoSupport {
  21. @Resource(name = "sessionFactory")
  22. public void setSuperSessionFactory(SessionFactory sessionFactory) {
  23. super.setSessionFactory(sessionFactory);
  24. }
  25. /**
  26. * 使用sql语句进行分页查询
  27. *
  28. * @param sql
  29. *            sql语句
  30. * @param values
  31. *            参数
  32. * @param offSet
  33. *            第一条记录序号 >-1
  34. * @param pageSize
  35. *            每页要显示的记录数 >0
  36. * @param beanClass
  37. *            将查询结果转换为<tt>T</tt>对象
  38. * @param fieldList
  39. *            查询Bean的成员变量名称
  40. */
  41. @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
  42. public List<T> list(final String sql, final Object[] values, final int offSet, final int pageSize,
  43. final Class<T> beanClass, final List<String> fieldList) {
  44. List<T> list = getHibernateTemplate().executeFind(new HibernateCallback() {
  45. public Object doInHibernate(Session session) throws HibernateException, SQLException {
  46. SQLQuery sqlQuery = session.createSQLQuery(sql);
  47. // 添加要查询字段的标量
  48. AddScalar.addSclar(sqlQuery, beanClass, fieldList);
  49. Query query = sqlQuery;
  50. // 转换查询结果为T
  51. if (beanClass != null) {
  52. query.setResultTransformer(Transformers.aliasToBean(beanClass));
  53. }
  54. if ((values != null) && values.length > 0) {
  55. int i = 0;
  56. for (Object obj : values) {
  57. query.setParameter(i++, obj);
  58. }
  59. }
  60. if (offSet > -1) {
  61. query.setFirstResult(offSet);
  62. }
  63. if (pageSize > 0) {
  64. query.setMaxResults(pageSize);
  65. }
  66. return query.list();
  67. }
  68. });
  69. return list;
  70. }
  71. }

亮点在代码中注释的两句。其中AddScalar.addSclar是自己写的,具体请看代码:

  1. package com.sourcefour.dao.base;
  2. import java.lang.reflect.Field;
  3. import java.util.Date;
  4. import java.util.List;
  5. import org.hibernate.Hibernate;
  6. import org.hibernate.SQLQuery;
  7. /**
  8. * @author sourcefour
  9. */
  10. public class AddScalar {
  11. /**
  12. * 将field type 和 Hibernate的类型进行了对应。这里其实不是多余的,如果不进行一定的对应可能会有问题。
  13. * 问题有两个:
  14. *  1. 在oracle中我们可能把一些字段设为NUMBER(%),而在Bean中的字段定的是long。那么查询时可能会报:
  15. *     java.math.BeigDecimal不能转换成long等错误
  16. *  2. 如果不这样写的话,可能Bean中的field就得是大写的,如:name就得写成NAME,userCount就得写成USERCOUNT
  17. *     这样是不是很扯(V_V)
  18. *
  19. * @param <T>
  20. * @param sqlQuery
  21. *            SQLQuery
  22. * @param clazz
  23. *            T.class
  24. * @param fieldList
  25. *            要查询的成员变量名称
  26. */
  27. public static <T> void addSclar(SQLQuery sqlQuery, Class<T> clazz, List<String> fieldList) {
  28. if (clazz == null) {
  29. throw new NullPointerException("[clazz] could not be null!");
  30. }
  31. if ((fieldList != null) && (fieldList.size() > 0)) {
  32. Field[] fields = clazz.getDeclaredFields();
  33. for (String fieldName : fieldList) {
  34. for (Field field : fields) {
  35. if (fieldName.equals(field.getName())) {
  36. if ((field.getType() == long.class) || (field.getType() == Long.class)) {
  37. sqlQuery.addScalar(field.getName(), Hibernate.LONG);
  38. } else if ((field.getType() == int.class) || (field.getType() == Integer.class)) {
  39. sqlQuery.addScalar(field.getName(), Hibernate.INTEGER);
  40. } else if ((field.getType() == char.class) || (field.getType() == Character.class)) {
  41. sqlQuery.addScalar(field.getName(), Hibernate.CHARACTER);
  42. } else if ((field.getType() == short.class) || (field.getType() == Short.class)) {
  43. sqlQuery.addScalar(field.getName(), Hibernate.SHORT);
  44. } else if ((field.getType() == double.class) || (field.getType() == Double.class)) {
  45. sqlQuery.addScalar(field.getName(), Hibernate.DOUBLE);
  46. } else if ((field.getType() == float.class) || (field.getType() == Float.class)) {
  47. sqlQuery.addScalar(field.getName(), Hibernate.FLOAT);
  48. } else if ((field.getType() == boolean.class) || (field.getType() == Boolean.class)) {
  49. sqlQuery.addScalar(field.getName(), Hibernate.BOOLEAN);
  50. } else if (field.getType() == String.class) {
  51. sqlQuery.addScalar(field.getName(), Hibernate.STRING);
  52. } else if (field.getType() == Date.class) {
  53. sqlQuery.addScalar(field.getName(), Hibernate.TIMESTAMP);
  54. }
  55. }
  56. }
  57. }
  58. }
  59. }
  60. }

所有的准备工作都做好了,那么就看我们的具体的DAO操作及单元测试。

具体DAO:

  1. package com.sourcefour.dao;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import org.springframework.stereotype.Repository;
  5. import com.sourcefour.bean.NativeSqlBean;
  6. import com.sourcefour.dao.base.BaseDaoSupport;
  7. /**
  8. * @author sourcefour
  9. */
  10. @Repository
  11. public class NativeSqlDao extends BaseDaoSupport<NativeSqlBean> {
  12. public List<NativeSqlBean> listAll(int offSet, int pageSize) {
  13. String sql = "SELECT MAX(t.mos) maxMos, MIN(t.mos) minMos, AVG(t.mos) avgMos, COUNT(t.id) userCount FROM t_native_sql t";
  14. List<String> fieldList = new ArrayList<String>();
  15. fieldList.add("maxMos");
  16. fieldList.add("minMos");
  17. fieldList.add("avgMos");
  18. fieldList.add("userCount");
  19. return super.list(sql, new Object[] {}, offSet, pageSize, NativeSqlBean.class, fieldList);
  20. }
  21. }

说明:sql语句中的别名就是我们Bean中的字段

Junit测试代码:

  1. package com.sourcefour.test.dao;
  2. import java.util.List;
  3. import org.junit.Assert;
  4. import org.junit.BeforeClass;
  5. import org.junit.Test;
  6. import org.springframework.context.ApplicationContext;
  7. import org.springframework.context.support.ClassPathXmlApplicationContext;
  8. import com.sourcefour.bean.NativeSqlBean;
  9. import com.sourcefour.dao.NativeSqlDao;
  10. /**
  11. * @author sourcefour
  12. */
  13. public class NativeSqlDaoTest {
  14. private static NativeSqlDao nativeSqlDao;
  15. private static ApplicationContext applicationContext;
  16. @BeforeClass
  17. public static void setUp() {
  18. applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
  19. nativeSqlDao = (NativeSqlDao) applicationContext.getBean("nativeSqlDao");
  20. }
  21. @Test
  22. public void testListIntInt() {
  23. List<NativeSqlBean> list = nativeSqlDao.listAll(-1, -1);
  24. Assert.assertNotNull(list);
  25. for (NativeSqlBean nativeSqlBean : list) {
  26. System.out.println("maxMos: " + nativeSqlBean.getMaxMos());
  27. }
  28. }
  29. }

运行结果:

到了这里应该说一切OK鸟。

完整的文档,SQL,工程下载地址:CSDN下载

说明:本说明是关于资源附件的,在资源中附件名称叫做 ‘hibernate将本地SQL查询结果封装成对象(最终)’,其实只有一版,这里只所以叫最终版是因为该附件我上传了好几天传不上去,到最后报告说‘资源已经存在’,但我确实没有看到附件。所以没办法只能改个名字了…………

hibernate将本地SQL查询结果封装成对象的更多相关文章

  1. Hibernate之QBC查询与本地SQL查询

    1. QBC查询:     QBC 查询就是通过使用Hibernate提供的QueryByCriteria API 来查询对象,这种API封装了SQL语句的动态拼装,对查询提供了更加面向对象的功能接口 ...

  2. Hibernate的四种查询方式(主键查询,HQL查询,Criteria查询,本地sql查询)和修改和添加

    Hibernate的添加,修改,查询(三种查询方式)的方法: 案例演示: 1:第一步,导包,老生常谈了都是,省略: 2:第二步,创建数据库和数据表,表结构如下所示: 3:第三步创建实体类User.ja ...

  3. 13.hibernate的native sql查询(转自xiaoluo501395377)

    hibernate的native sql查询   在我们的hibernate中,除了我们常用的HQL查询以外,还非常好的支持了原生的SQL查询,那么我们既然使用了hibernate,为什么不都采用hi ...

  4. hibernate的native sql查询

    在我们的hibernate中,除了我们常用的HQL查询以外,还非常好的支持了原生的SQL查询,那么我们既然使用了hibernate,为什么不都采用hibernate推荐的HQL查询语句呢?这是因为HQ ...

  5. 本地SQL查询

    -------------------siwuxie095 本地 SQL 查询 1.简单介绍 采用 HQL 或 QBC 查询时,Hibernate 生成标准的 SQL 语句, 适用于所有的数据库平台, ...

  6. hibernate 5原生sql查询测试学习代码

    基本查询 import java.util.List; import org.hibernate.SQLQuery; import org.hibernate.Session; import org. ...

  7. hibernate使用原生SQL查询返回结果集的处理

    今天没事的时候,看到公司框架里有一个用原生SQL写的函数,说实在以前自己也干过这事,但好久都没有用,都忘得差不多了,现在基本都是用的hql语句来查询结果.hibernate中使用createSQLQu ...

  8. Hibernate SQLQuery 原生SQL 查询及返回结果集处理-1

    第一篇:官方文档的处理方法,摘自官方 在迁移原先用JDBC/SQL实现的系统,难免需要采用hibernat native sql支持. 1.使用SQLQuery hibernate对原生SQL查询执行 ...

  9. Java JDBC利用反射技术将查询结果封装为对象

    1.JDBC将返回结果集封装成对象demo class JdbcDemo { /** * 获取数据库列名 * @param rs * @return */ private static String[ ...

随机推荐

  1. Linux 中文乱码问题

    弄了好久还是乱码 最终方法:进入 vim /etc/vimrc中 原先只有一个 set encoding=utf-8 fileencodings=ucs-bom,utf-8,cp936改成: let ...

  2. 【读书笔记】读《JavaScript设计模式》之桥接模式

    桥接模式(Bridge)将抽象部分与它的实现部分分离,使它们都可以独立地变化. 一.使用场景 使用场景一:事件监控 对于前端而言,最典型的使用场景——事件监控.如—— addEvent(element ...

  3. struts2中各种值栈问题

    struts2中OGNL和 ValueStack(一) 收藏 学习的时候,总分不清楚在struts2中页面的传值和取值是怎么来完成的,所以从网上搜了很多资料,现在把这些资料总结写,留着以后参考..看完 ...

  4. PHP单引号和双引号的区别

    单引号和双引号的区别 .双引号 里的东西 输入的时候能判断是否 包含 变量,如果包含 变量 就一起输出 .单引号里的就不一样,不判断是否有变量,就全部当成 字符串 输出 .单引号解析的时间比双引号快 ...

  5. 电赛菜鸟营培训(五)——OLED屏幕的使用

    一.取模软件的使用 首先进行设置 然后可以生成显示这个字母的代码,列优先,先按列画8行,然后再继续画下一列.汉字为16*16,字母为8*8,对应生成相应个数的ox代码. 二.STM32烤写OLED # ...

  6. burpsuite绕过本地javascripte上传文件

    burpsuite绕过本地javascripte上传文件   先是找到图片上传的位置:       上传个asp文件试试,一点击上传就出现:       这样基本就可以确定是本地检测文件后缀名的方式来 ...

  7. mac OS X操作--快捷键

  8. Rightmost Digit

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...

  9. iOS数组排序

    [_fields sortUsingComparator:^NSComparisonResult(UITextField *obj1, UITextField *obj2) { /* NSOrdere ...

  10. 5分钟上手写ECharts的第一个图表

    网址:http://echarts.baidu.com/doc/start.html 架构特性 http://echarts.baidu.com/doc/feature.html | 架构 提供商业产 ...