当前位置: 代码迷 >> SQL >> Hibernate_根据条件动态组建sql/hql语句(仿ibatis动态查询语句功能)
  详细解决方案

Hibernate_根据条件动态组建sql/hql语句(仿ibatis动态查询语句功能)

热度:156   发布时间:2016-05-05 11:19:01.0
Hibernate_根据条件动态组装sql/hql语句(仿ibatis动态查询语句功能)

via: http://blog.csdn.net/crazycoder2010/article/details/7414152

?

1.功能需求背景
? 项目中使用hibernate作为数据持久层框架,主要考虑hibernate在进行一些简单的crud操作时非常便利,不需要和ibatis似的为每个sql操作都写一堆文件,但是同时也带来了一些局限性,如类似ibatis强大的动态查询功能用不了了,但是这个功能在项目中的应用场景又很大,hibernate自身也支持将sql/hql语句写在.hbm.xml映射文件中<sql-query>和<query>元素,但是这个功能只能对那些查询限制条件固定的sql有用,对于需要动态拼接的sql语句,hibernate就显得力不从心了,如何给hibernate插上ibatis动态查询的翅膀,既保留crud的简洁性,又能收获ibatis的特性呢?接下来的文章将会重点介绍
2.设计思路
? 先看一下ibatis的动态查询时怎么做的
???? <select id="getUserList" resultMap="user">
???????? select * from user
??????????? <isGreaterThan prepend="and" property="id" compareValue="0">
?????????????????? where user_id = #userId#
??????????? </isGreaterThan>
???????????? order by createTime desc
??? </select>
? ibatis在程序实现内部回去解析sql语句中的标签,然后去解析计算,我们在ibatis在实现的时候也参考了这个解决思路,但是否是需要把ibatis里的解析sql的语法都抄到我们的dao框架中呢-显然这样太复杂了,而且ibatis自己的sql元素是和那些resultMap等是绑定在一起用的,而在hibernate是没用这些东西的,要改造这些东西是一项非常浩大的工程,因此这个方案被放弃了

? 我们在实现的时候采取了一种非常简洁又功能强大的方式-模板技术!对,就是利用freemarker把sql/hql中的动态拼接条件判断语法都交给freemarker语法去处理,这样既能复用freemarker框架,又保持了我们框架设计的简洁性-不需要自己写过多的处理逻辑,以下是我们需要进行动态处理的sql/hql语句的样例

[html]?view plaincopyprint?
?
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <!DOCTYPE?dynamic-hibernate-statement?PUBLIC?"-//Haier/HOP?Hibernate?Dynamic?Statement?DTD?1.0//EN"??
  3. "http://www.haier.com/dtd/dynamic-hibernate-statement-1.0.dtd">??
  4. <dynamic-hibernate-statement>??
  5. ????<!--?查询某个资源下的直接子节点?-->??
  6. ????<hql-query?name="resource.getChildren">??
  7. ????<![CDATA[?
  8. ????????from?Resource?where?parent.id=${parentId}?and?parent.id?!=?id?
  9. ????]]>???
  10. ????</hql-query>??
  11. ????<!--?查询系统中所有的root资源?-->??
  12. ????<hql-query?name="resource.getRoots">??
  13. ????<![CDATA[?
  14. ????????from?Resource?where?parent.id?=?id?order?by?orderIndex?
  15. ????]]>???
  16. ????</hql-query>??
  17. ????<!--?获取某个用户可访问的某个资源下的所有子资源?-->??
  18. ????<sql-query?name="resource.getDescendants">??
  19. ????<![CDATA[?
  20. ????????select?distinct?t.id,?
  21. ????????????????????????t.name,?
  22. ????????????????????????t.description,?
  23. ????????????????????????t.url,?
  24. ????????????????????????t.type,?
  25. ????????????????????????t.status,?
  26. ????????????????????????t.code,?
  27. ????????????????????????t.configuration,?
  28. ????????????????????????t.module_name,?
  29. ????????????????????????t.gmt_create,?
  30. ????????????????????????t.gmt_modified,?
  31. ????????????????????????t.create_by,?
  32. ????????????????????????t.last_modified_by,?
  33. ????????????????????????t.order_index,?
  34. ????????????????????????t.parent_id?
  35. ??????????from?resource_info?t?
  36. ?????????inner?join?role_resource?rr?
  37. ????????????on?t.id?=?rr.resource_id?
  38. ?????????inner?join?user_role?ur?
  39. ????????????on?rr.role_id?=?ur.role_id?
  40. ?????????where?ur.user_id?=?${userId}?
  41. ?????????<#if?type?==?'1'>?
  42. ????????????and?t.type=1?
  43. ????????????<#else>?
  44. ????????????and?t.type=0?
  45. ?????????</#if>?
  46. ???????????and?t.type?=??${type}?
  47. ???????????and?t.status?=??${status}?
  48. ?????????start?with?t.code?=?'${code}'?
  49. ????????connect?by?nocycle?prior?t.id?=?t.parent_id?
  50. ????]]>???
  51. ????</sql-query>??
  52. </dynamic-hibernate-statement>??

这个文件看起来非常类似ibatis的语句了,只是没用ibatis的哪些标签-改成了freemarker语法,没错,我们就是复用freemarker来帮我们解决这些烦杂的判断操作的

这样我们的动态sql程序就可以总结成以下流程

a.系统加载阶段

? 这个阶段程序负责将指定路径下的动态sql文件加载到内存中,一次性缓存起来,没错,这些东西只需要加载一次,以后直接读取就行了,没必要每次去查找,缓存也非常简单,一个Map<String,String>就搞定,key是sql-query或hql-query元素的name属性,value就是与其对应的sql/hql语句

b.程序调用查询阶段

?? 调用程序通过sql/hql语句的name属性和传入查询参数来得到最终解析出来的语句

我们期望的方法可能是这样的:

[java]?view plaincopyprint?
?
  1. public?<X>?List<X>?findByNamedQuery(final?String?queryName,?final?Map<String,??>?parameters)???

通过queryName从缓存中查找出其对应的sql/hql语句(最原始的,里面带有freemarker语法)

然后通过freemarker模板和传递进去的parameters参数对模板进行解析,得到最终的语句(纯sql/hql)

最后将解析后的sql/hql传递给底层api,返回查询结果

3.实现

? 上面介绍了大致的思路,这里介绍具体的代码实现

? 3.1DTD定义

????? 我们是把动态的sql/hql语句放在单独的xml配置文件里的,为了规范xml文档,我们给文档定义了dtd文件,这里我们只定义了两个元素<sql-query>和<hql-query>分别表示sql查询语句和hql查询语句,这两个元素目前自有一个name属性用来唯一标示该语句,如下

[html]?view plaincopyprint?
?
  1. <!--?HOP?Hibernate?Dynamic?Statement?Mapping?DTD.??
  2. ??
  3. <!DOCTYPE?dynamic-hibernate-statement?PUBLIC???
  4. ????"-//Haier/HOP?Hibernate?Dynamic?Statement?DTD?1.0//EN"??
  5. ????"http://www.haier.com/dtd/dynamic-hibernate-statement-1.0.dtd">??
  6. ??
  7. 这个文件时用来定义动态参数语句,类似itabis??
  8. ??
  9. -->??
  10. ??
  11. <!--?
  12. ????The?document?root.?
  13. ?-->??
  14. ??
  15. <!ELEMENT?dynamic-hibernate-statement?(??
  16. ????(hql-query|sql-query)*??
  17. )>??
  18. ????????????????????????????<!--?default:?none?-->??
  19. ??
  20. <!--?The?query?element?declares?a?named?Hibernate?query?string?-->??
  21. ??
  22. <!ELEMENT?hql-query?(#PCDATA)>??
  23. ????<!ATTLIST?hql-query?name?CDATA?#REQUIRED>??
  24. ??
  25. <!--?The?sql-query?element?declares?a?named?SQL?query?string?-->??
  26. ??
  27. <!ELEMENT?sql-query?(#PCDATA)>??
  28. ????<!ATTLIST?sql-query?name?CDATA?#REQUIRED>??

然后将其保存为dynamic-hibernate-statement-1.0.dtd,放在classpath下

编写DTD校验器

?

[java]?view plaincopyprint?
?
  1. /**?
  2. ?*?hibernate动态sql?dtd解析器?
  3. [email protected]?
  4. ?*?
  5. ?*/??
  6. public?class?DynamicStatementDTDEntityResolver?implements?EntityResolver,?Serializable{??
  7. ????private?static?final?long?serialVersionUID?=?8123799007554762965L;??
  8. ????private?static?final?Logger?LOGGER?=?LoggerFactory.getLogger(?DynamicStatementDTDEntityResolver.class?);??
  9. ????private?static?final?String?HOP_DYNAMIC_STATEMENT?=?"http://www.haier.com/dtd/";??
  10. ??
  11. ????public?InputSource?resolveEntity(String?publicId,?String?systemId)?{??
  12. ????????InputSource?source?=?null;?//?returning?null?triggers?default?behavior??
  13. ????????if?(?systemId?!=?null?)?{??
  14. ????????????LOGGER.debug(?"trying?to?resolve?system-id?["?+?systemId?+?"]"?);??
  15. ????????????if?(?systemId.startsWith(?HOP_DYNAMIC_STATEMENT?)?)?{??
  16. ????????????????LOGGER.debug(?"recognized?hop?dyanmic?statement?namespace;?attempting?to?resolve?on?classpath?under?com/haier/openplatform/dao/hibernate/"?);??
  17. ????????????????source?=?resolveOnClassPath(?publicId,?systemId,?HOP_DYNAMIC_STATEMENT?);??
  18. ????????????}??
  19. ????????}??
  20. ????????return?source;??
  21. ????}??
  22. ??
  23. ????private?InputSource?resolveOnClassPath(String?publicId,?String?systemId,?String?namespace)?{??
  24. ????????InputSource?source?=?null;??
  25. ????????String?path?=?"com/haier/openplatform/dao/hibernate/"?+?systemId.substring(?namespace.length()?);??
  26. ????????InputStream?dtdStream?=?resolveInHibernateNamespace(?path?);??
  27. ????????if?(?dtdStream?==?null?)?{??
  28. ????????????LOGGER.debug(?"unable?to?locate?["?+?systemId?+?"]?on?classpath"?);??
  29. ????????????if?(?systemId.substring(?namespace.length()?).indexOf(?"2.0"?)?>?-1?)?{??
  30. ????????????????LOGGER.error(?"Don't?use?old?DTDs,?read?the?Hibernate?3.x?Migration?Guide!"?);??
  31. ????????????}??
  32. ????????}??
  33. ????????else?{??
  34. ????????????LOGGER.debug(?"located?["?+?systemId?+?"]?in?classpath"?);??
  35. ????????????source?=?new?InputSource(?dtdStream?);??
  36. ????????????source.setPublicId(?publicId?);??
  37. ????????????source.setSystemId(?systemId?);??
  38. ????????}??
  39. ????????return?source;??
  40. ????}??
  41. ??
  42. ????protected?InputStream?resolveInHibernateNamespace(String?path)?{??
  43. ????????return?this.getClass().getClassLoader().getResourceAsStream(?path?);??
  44. ????}??
  45. ??
  46. ????protected?InputStream?resolveInLocalNamespace(String?path)?{??
  47. ????????try?{??
  48. ????????????return?ConfigHelper.getUserResourceAsStream(?path?);??
  49. ????????}??
  50. ????????catch?(?Throwable?t?)?{??
  51. ????????????return?null;??
  52. ????????}??
  53. ????}??
  54. }??

?

3.2编写sql文件

[html]?view plaincopyprint?
?
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <!DOCTYPE?dynamic-hibernate-statement?PUBLIC?"-//Haier/HOP?Hibernate?Dynamic?Statement?DTD?1.0//EN"??
  3. "http://www.haier.com/dtd/dynamic-hibernate-statement-1.0.dtd">??
  4. <dynamic-hibernate-statement>??
  5. ????<!--?查询某个资源下的直接子节点?-->??
  6. ????<hql-query?name="resource.getChildren">??
  7. ????<![CDATA[?
  8. ????????from?Resource?where?parent.id=${parentId}?and?parent.id?!=?id?
  9. ????]]>???
  10. ????</hql-query>??
  11. ????<!--?查询系统中所有的root资源?-->??
  12. ????<hql-query?name="resource.getRoots">??
  13. ????<![CDATA[?
  14. ????????from?Resource?where?parent.id?=?id?order?by?orderIndex?
  15. ????]]>???
  16. ????</hql-query>??
  17. ????<!--?获取某个用户可访问的某个资源下的所有子资源?-->??
  18. ????<sql-query?name="resource.getDescendants">??
  19. ????<![CDATA[?
  20. ????????select?distinct?t.id,?
  21. ????????????????????????t.name,?
  22. ????????????????????????t.description,?
  23. ????????????????????????t.url,?
  24. ????????????????????????t.type,?
  25. ????????????????????????t.status,?
  26. ????????????????????????t.code,?
  27. ????????????????????????t.configuration,?
  28. ????????????????????????t.module_name,?
  29. ????????????????????????t.gmt_create,?
  30. ????????????????????????t.gmt_modified,?
  31. ????????????????????????t.create_by,?
  32. ????????????????????????t.last_modified_by,?
  33. ????????????????????????t.order_index,?
  34. ????????????????????????t.parent_id?
  35. ??????????from?resource_info?t?
  36. ?????????inner?join?role_resource?rr?
  37. ????????????on?t.id?=?rr.resource_id?
  38. ?????????inner?join?user_role?ur?
  39. ????????????on?rr.role_id?=?ur.role_id?
  40. ?????????where?ur.user_id?=?${userId}?
  41. ?????????<#if?type?==?'1'>?
  42. ????????????and?t.type=1?
  43. ????????????<#else>?
  44. ????????????and?t.type=0?
  45. ?????????</#if>?
  46. ???????????and?t.type?=??${type}?
  47. ???????????and?t.status?=??${status}?
  48. ?????????start?with?t.code?=?'${code}'?
  49. ????????connect?by?nocycle?prior?t.id?=?t.parent_id?
  50. ????]]>???
  51. ????</sql-query>??
  52. </dynamic-hibernate-statement>??

3.3加载动态sql文件

这里我们将加载sql/hql语句的程序独立到一个单独的类中,以便独立扩展

这里一共3个方法,分表标示获取系统中sql/hql语句的map(key:语句名称,value:具体的)

[java]?view plaincopyprint?
?
  1. /**?
  2. ?*?动态sql/hql语句组装器?
  3. [email protected]?
  4. ?*?
  5. ?*/??
  6. public?interface?DynamicHibernateStatementBuilder?{??
  7. ????/**?
  8. ?????*?hql语句map?
  9. [email protected]?
  10. ?????*/??
  11. ????public?Map<String,String>?getNamedHQLQueries();??
  12. ????/**?
  13. ?????*?sql语句map?
  14. [email protected]?
  15. ?????*/??
  16. ????public?Map<String,String>?getNamedSQLQueries();??
  17. ????/**?
  18. ?????*?初始化?
  19. [email protected]?
  20. ?????*/??
  21. ????public?void?init()?throws?IOException;??
  22. }??

默认的加载器-将指定配置文件中的sql/hql语句加载到内存中

[java]?view plaincopyprint?
?
  1. /**?
  2. [email protected]?
  3. ?*?
  4. ?*/??
  5. public?class?DefaultDynamicHibernateStatementBuilder?implements?DynamicHibernateStatementBuilder,?ResourceLoaderAware?{??
  6. ????private?static?final?Logger?LOGGER?=?LoggerFactory.getLogger(DefaultDynamicHibernateStatementBuilder.class);??
  7. ????private?Map<String,?String>?namedHQLQueries;??
  8. ????private?Map<String,?String>?namedSQLQueries;??
  9. ????private?String[]?fileNames?=?new?String[0];??
  10. ????private?ResourceLoader?resourceLoader;??
  11. ????private?EntityResolver?entityResolver?=?new?DynamicStatementDTDEntityResolver();??
  12. ????/**?
  13. ?????*?查询语句名称缓存,不允许重复?
  14. ?????*/??
  15. ????private?Set<String>?nameCache?=?new?HashSet<String>();??
  16. ??
  17. ????public?void?setFileNames(String[]?fileNames)?{??
  18. ????????this.fileNames?=?fileNames;??
  19. ????}??
  20. ??
  21. ????@Override??
  22. ????public?Map<String,?String>?getNamedHQLQueries()?{??
  23. ????????return?namedHQLQueries;??
  24. ????}??
  25. ??
  26. ????@Override??
  27. ????public?Map<String,?String>?getNamedSQLQueries()?{??
  28. ????????return?namedSQLQueries;??
  29. ????}??
  30. ??
  31. ????@Override??
  32. ????public?void?init()?throws?IOException?{??
  33. ????????namedHQLQueries?=?new?HashMap<String,?String>();??
  34. ????????namedSQLQueries?=?new?HashMap<String,?String>();??
  35. ????????boolean?flag?=?this.resourceLoader?instanceof?ResourcePatternResolver;??
  36. ????????for?(String?file?:?fileNames)?{??
  37. ????????????if?(flag)?{??
  38. ????????????????Resource[]?resources?=?((ResourcePatternResolver)?this.resourceLoader).getResources(file);??
  39. ????????????????buildMap(resources);??
  40. ????????????}?else?{??
  41. ????????????????Resource?resource?=?resourceLoader.getResource(file);??
  42. ????????????????buildMap(resource);??
  43. ????????????}??
  44. ????????}??
  45. ????????//clear?name?cache??
  46. ????????nameCache.clear();??
  47. ????}??
  48. ??
  49. ????@Override??
  50. ????public?void?setResourceLoader(ResourceLoader?resourceLoader)?{??
  51. ????????this.resourceLoader?=?resourceLoader;??
  52. ????}??
  53. ??
  54. ????private?void?buildMap(Resource[]?resources)?throws?IOException?{??
  55. ????????if?(resources?==?null)?{??
  56. ????????????return;??
  57. ????????}??
  58. ????????for?(Resource?resource?:?resources)?{??
  59. ????????????buildMap(resource);??
  60. ????????}??
  61. ????}??
  62. ??
  63. ????@SuppressWarnings({?"rawtypes"?})??
  64. ????private?void?buildMap(Resource?resource)?{??
  65. ????????InputSource?inputSource?=?null;??
  66. ????????try?{??
  67. ????????????inputSource?=?new?InputSource(resource.getInputStream());??
  68. ????????????XmlDocument?metadataXml?=?MappingReader.INSTANCE.readMappingDocument(entityResolver,?inputSource,??
  69. ????????????????????new?OriginImpl("file",?resource.getFilename()));??
  70. ????????????if?(isDynamicStatementXml(metadataXml))?{??
  71. ????????????????final?Document?doc?=?metadataXml.getDocumentTree();??
  72. ????????????????final?Element?dynamicHibernateStatement?=?doc.getRootElement();??
  73. ????????????????Iterator?rootChildren?=?dynamicHibernateStatement.elementIterator();??
  74. ????????????????while?(rootChildren.hasNext())?{??
  75. ????????????????????final?Element?element?=?(Element)?rootChildren.next();??
  76. ????????????????????final?String?elementName?=?element.getName();??
  77. ????????????????????if?("sql-query".equals(elementName))?{??
  78. ????????????????????????putStatementToCacheMap(resource,?element,?namedSQLQueries);??
  79. ????????????????????}?else?if?("hql-query".equals(elementName))?{??
  80. ????????????????????????putStatementToCacheMap(resource,?element,?namedHQLQueries);??
  81. ????????????????????}??
  82. ????????????????}??
  83. ????????????}??
  84. ????????}?catch?(Exception?e)?{??
  85. ????????????LOGGER.error(e.toString());??
  86. ????????????throw?new?SysException(e);??
  87. ????????}?finally?{??
  88. ????????????if?(inputSource?!=?null?&&?inputSource.getByteStream()?!=?null)?{??
  89. ????????????????try?{??
  90. ????????????????????inputSource.getByteStream().close();??
  91. ????????????????}?catch?(IOException?e)?{??
  92. ????????????????????LOGGER.error(e.toString());??
  93. ????????????????????throw?new?SysException(e);??
  94. ????????????????}??
  95. ????????????}??
  96. ????????}??
  97. ??
  98. ????}??
  99. ??
  100. ????private?void?putStatementToCacheMap(Resource?resource,?final?Element?element,?Map<String,?String>?statementMap)??
  101. ????????????throws?IOException?{??
  102. ????????String?sqlQueryName?=?element.attribute("name").getText();??
  103. ????????Validate.notEmpty(sqlQueryName);??
  104. ????????if?(nameCache.contains(sqlQueryName))?{??
  105. ????????????throw?new?SysException("重复的sql-query/hql-query语句定义在文件:"?+?resource.getURI()?+?"中,必须保证name的唯一.");??
  106. ????????}??
  107. ????????nameCache.add(sqlQueryName);??
  108. ????????String?queryText?=?element.getText();??
  109. ????????statementMap.put(sqlQueryName,?queryText);??
  110. ????}??
  111. ??
  112. ????private?static?boolean?isDynamicStatementXml(XmlDocument?xmlDocument)?{??
  113. ????????return?"dynamic-hibernate-statement".equals(xmlDocument.getDocumentTree().getRootElement().getName());??
  114. ????}??
  115. }??

配置一下

[html]?view plaincopyprint?
?
  1. ????<bean?id="dynamicStatementBuilder"?class="com.haier.openplatform.dao.hibernate.support.DefaultDynamicHibernateStatementBuilder">??
  2. ????????<property?name="fileNames">??
  3. ????????????<list>??
  4. ????????????????<value>classpath*:/**/*-dynamic.xml</value><!--这里我们指定要加载某个文件夹下所有以-dynamic.xml结尾的文件?-->??
  5. ????????????</list>??
  6. ????????</property>??
  7. ????</bean>??
  8. ????<bean?id="baseHibernateDAO"?class="com.haier.openplatform.dao.hibernate.BaseDAOHibernateImpl"?abstract="true">??
  9. ????????<property?name="sessionFactory">??
  10. ????????????<ref?bean="sessionFactory"/>??
  11. ????????</property>??
  12. ????????<property?name="dynamicStatementBuilder"?ref="dynamicStatementBuilder"/>??
  13. ????</bean>??

dao层代码

[java]?view plaincopyprint?
?
  1. /**?
  2. ?*?Hibernate实现的DAO层?
  3. [email protected]<T>?DAO操作的对象类型?
  4. [email protected]<ID>?主键类型?
  5. [email protected]?
  6. ?*?
  7. ?*/??
  8. public?class?SimpleHibernateDAO<T,ID?extends?Serializable>?implements?BaseDAO<T,?ID>,InitializingBean{??
  9. ????private?static?final?Logger?LOGER?=?LoggerFactory.getLogger(SimpleHibernateDAO.class);??
  10. ????protected?SessionFactory?sessionFactory;??
  11. ????protected?Class<T>?entityClass;??
  12. ????/**?
  13. ?????*?模板缓存?
  14. ?????*/??
  15. ????protected?Map<String,?StatementTemplate>?templateCache;??
  16. ????protected?DynamicHibernateStatementBuilder?dynamicStatementBuilder;??
  17. ????/**?
  18. ?????*?通过子类的泛型定义取得对象类型Class.?
  19. ?????*?eg.?
  20. ?????*?public?class?UserDao?extends?SimpleHibernateDao<User,?Long>?
  21. ?????*/??
  22. ????public?SimpleHibernateDAO()?{??
  23. ????????this.entityClass?=?Reflections.getSuperClassGenricType(getClass());??
  24. ????}??
  25. ??
  26. ????/**?
  27. ?????*?取得sessionFactory.?
  28. ?????*/??
  29. ????public?SessionFactory?getSessionFactory()?{??
  30. ????????return?sessionFactory;??
  31. ????}??
  32. ??
  33. ????/**?
  34. [email protected],?当有多个SesionFactory的时候在子类重载本函数.?
  35. ?????*/??
  36. ????public?void?setSessionFactory(final?SessionFactory?sessionFactory)?{??
  37. ????????this.sessionFactory?=?sessionFactory;??
  38. ????}??
  39. ??
  40. ????public?void?setDynamicStatementBuilder(DynamicHibernateStatementBuilder?dynamicStatementBuilder)?{??
  41. ????????this.dynamicStatementBuilder?=?dynamicStatementBuilder;??
  42. ????}??
  43. ??
  44. ????/**?
  45. ?????*?取得当前Session.?
  46. ?????*/??
  47. ????public?Session?getSession()?{??
  48. ????????return?sessionFactory.getCurrentSession();??
  49. ????}??
  50. ??
  51. ????/**?
  52. ?????*?保存新增或修改的对象.?
  53. ?????*/??
  54. ????@Override??
  55. ????public?void?save(final?T?entity)?{??
  56. ????????Validate.notNull(entity,?"entity不能为空");??
  57. ????????getSession().save(entity);??
  58. ????????LOGER.debug("save?entity:?{}",?entity);??
  59. ????}??
  60. ??
  61. ????/**?
  62. ?????*?删除对象.?
  63. ?????*??
  64. [email protected]?含id属性的transient对象.?
  65. ?????*/??
  66. ????@Override??
  67. ????public?void?delete(final?T?entity)?{??
  68. ????????if(entity?==?null){??
  69. ????????????return;??
  70. ????????}??
  71. ????????getSession().delete(entity);??
  72. ????????LOGER.debug("delete?entity:?{}",?entity);??
  73. ????}??
  74. ??
  75. ????/**?
  76. ?????*?按id删除对象.?
  77. ?????*/??
  78. ????@Override??
  79. ????public?void?delete(final?ID?id)?{??
  80. ????????Validate.notNull(id,?"id不能为空");??
  81. ????????delete(get(id));??
  82. ????????LOGER.debug("delete?entity?{},id?is?{}",?entityClass.getSimpleName(),?id);??
  83. ????}??
  84. ??
  85. ????/**?
  86. ?????*?按id获取对象.?
  87. ?????*/??
  88. ????@SuppressWarnings("unchecked")??
  89. ????@Override??
  90. ????public?T?get(final?ID?id)?{??
  91. ????????Validate.notNull(id,?"id不能为空");??
  92. ????????return?(T)?getSession().get(entityClass,?id);??
  93. ????}??
  94. ??
  95. ????/**?
  96. ?????*?按id列表获取对象列表.?
  97. ?????*/??
  98. ????public?List<T>?get(final?Collection<ID>?ids)?{??
  99. ????????return?find(Restrictions.in(getIdName(),?ids));??
  100. ????}??
  101. ??
  102. ????/**?
  103. ?????*??获取全部对象.?
  104. ?????*/??
  105. ????@Override??
  106. ????public?List<T>?getAll()?{??
  107. ????????return?find();??
  108. ????}??
  109. ??
  110. ????/**?
  111. ?????*??获取全部对象,?支持按属性行序.?
  112. ?????*/??
  113. ????@SuppressWarnings("unchecked")??
  114. ????public?List<T>?getAll(String?orderByProperty,?boolean?isAsc)?{??
  115. ????????Criteria?c?=?createCriteria();??
  116. ????????if?(isAsc)?{??
  117. ????????????c.addOrder(Order.asc(orderByProperty));??
  118. ????????}?else?{??
  119. ????????????c.addOrder(Order.desc(orderByProperty));??
  120. ????????}??
  121. ????????return?c.list();??
  122. ????}??
  123. ??
  124. ????/**?
  125. ?????*?按属性查找对象列表,?匹配方式为相等.?
  126. ?????*/??
  127. ????public?List<T>?findBy(final?String?propertyName,?final?Object?value)?{??
  128. ????????Criterion?criterion?=?Restrictions.eq(propertyName,?value);??
  129. ????????return?find(criterion);??
  130. ????}??
  131. ??
  132. ????/**?
  133. ?????*?按属性查找唯一对象,?匹配方式为相等.?
  134. ?????*/??
  135. ????@SuppressWarnings("unchecked")??
  136. ????@Override??
  137. ????public?T?findUniqueBy(final?String?propertyName,?final?Object?value)?{??
  138. ????????Criterion?criterion?=?Restrictions.eq(propertyName,?value);??
  139. ????????return?((T)?createCriteria(criterion).uniqueResult());??
  140. ????}??
  141. ??
  142. ????/**?
  143. ?????*?按HQL查询对象列表.?
  144. ?????*??
  145. [email protected],按顺序绑定.?
  146. ?????*/??
  147. ????@SuppressWarnings("unchecked")??
  148. ????public?<X>?List<X>?findByHQL(final?String?hql,?final?Object...?values)?{??
  149. ????????return?createHQLQuery(hql,?values).list();??
  150. ????}??
  151. ??????
  152. ????/**?
  153. ?????*?按HQL查询对象列表,并将对象封装成指定的对象?
  154. ?????*??
  155. [email protected],按顺序绑定.?
  156. ?????*/??
  157. ????@SuppressWarnings("unchecked")??
  158. ????public?<X>?List<X>?findByHQLRowMapper(RowMapper<X>?rowMapper,final?String?hql,?final?Object...?values)?{??
  159. ????????Validate.notNull(rowMapper,?"rowMapper不能为空!");??
  160. ????????List<Object[]>?result?=?createHQLQuery(hql,?values).list();??
  161. ????????return?buildListResultFromRowMapper(rowMapper,?result);??
  162. ????}??
  163. ??
  164. ????protected?<X>?List<X>?buildListResultFromRowMapper(RowMapper<X>?rowMapper,?List<Object[]>?result)?{??
  165. ????????List<X>?rs?=?new?ArrayList<X>(result.size());??
  166. ????????for(Object[]?obj?:?result){??
  167. ????????????rs.add(rowMapper.fromColumn(obj));??
  168. ????????}??
  169. ????????return?rs;??
  170. ????}??
  171. ??????
  172. ??????
  173. ????/**?
  174. ?????*?按SQL查询对象列表.?
  175. ?????*??
  176. [email protected],按顺序绑定.?
  177. ?????*/??
  178. ????@SuppressWarnings("unchecked")??
  179. ????public?<X>?List<X>?findBySQLRowMapper(RowMapper<X>?rowMapper,final?String?sql,?final?Object...?values)?{??
  180. ????????Validate.notNull(rowMapper,?"rowMapper不能为空!");??
  181. ????????List<Object[]>?result?=?createSQLQuery(sql,?values).list();??
  182. ????????return?buildListResultFromRowMapper(rowMapper,?result);??
  183. ????}??
  184. ??????
  185. ????/**?
  186. ?????*?按SQL查询对象列表,并将结果集转换成指定的对象列表?
  187. ?????*??
  188. [email protected],按顺序绑定.?
  189. ?????*/??
  190. ????@SuppressWarnings("unchecked")??
  191. ????public?<X>?List<X>?findBySQL(final?String?sql,?final?Object...?values)?{??
  192. ????????return?createSQLQuery(sql,?values).list();??
  193. ????}??
  194. ??
  195. ????/**?
  196. ?????*?按HQL查询对象列表.?
  197. ?????*??
  198. [email protected],按名称绑定.?
  199. ?????*/??
  200. ????@SuppressWarnings("unchecked")??
  201. ????public?<X>?List<X>?findByHQL(final?String?hql,?final?Map<String,??>?values)?{??
  202. ????????return?createHQLQuery(hql,?values).list();??
  203. ????}??
  204. ??????
  205. ????/**?
  206. ?????*?按HQL查询对象列表,并将结果集封装成对象列表?
  207. ?????*??
  208. [email protected],按名称绑定.?
  209. ?????*/??
  210. ????@SuppressWarnings("unchecked")??
  211. ????public?<X>?List<X>?findByHQLRowMapper(RowMapper<X>?rowMapper,final?String?hql,?final?Map<String,??>?values)?{??
  212. ????????Validate.notNull(rowMapper,?"rowMapper不能为空!");??
  213. ????????List<Object[]>?result?=?createHQLQuery(hql,?values).list();??
  214. ????????return?buildListResultFromRowMapper(rowMapper,?result);??
  215. ????}??
  216. ??????
  217. ????/**?
  218. ?????*?按SQL查询对象列表.?
  219. [email protected]?
  220. [email protected],按名称绑定.?
  221. ?????*/??
  222. ????@SuppressWarnings("unchecked")??
  223. ????public?<X>?List<X>?findBySQL(final?String?sql,?final?Map<String,??>?values)?{??
  224. ????????return?createSQLQuery(sql,?values).list();??
  225. ????}??
  226. ??????
  227. ????/**?
  228. ?????*?查询在xxx.hbm.xml中配置的查询语句?
  229. [email protected]?
  230. [email protected]?
  231. [email protected]?
  232. ?????*/??
  233. ????public?<X>?List<X>?findByNamedQuery(final?String?queryName,?final?Map<String,??>?parameters)?{??
  234. ????????StatementTemplate?statementTemplate?=?templateCache.get(queryName);??
  235. ????????String?statement?=?processTemplate(statementTemplate,parameters);??
  236. ????????if(statementTemplate.getType()?==?StatementTemplate.TYPE.HQL){??
  237. ????????????return?this.findByHQL(statement);??
  238. ????????}else{??
  239. ????????????return?this.findBySQL(statement);??
  240. ????????}??
  241. ????}??
  242. ??????
  243. ????/**?
  244. ?????*?查询在xxx.hbm.xml中配置的查询语句?
  245. [email protected]?
  246. [email protected]?
  247. [email protected]?
  248. [email protected]?
  249. ?????*/??
  250. ????public?<X>?List<X>?findByNamedQuery(RowMapper<X>?rowMapper,final?String?queryName,?final?Map<String,??>?parameters)?{??
  251. ????????StatementTemplate?statementTemplate?=?templateCache.get(queryName);??
  252. ????????String?statement?=?processTemplate(statementTemplate,parameters);??
  253. ????????if(statementTemplate.getType()?==?StatementTemplate.TYPE.HQL){??
  254. ????????????return?this.findByHQLRowMapper(rowMapper,statement);??
  255. ????????}else{??
  256. ????????????return?this.findBySQLRowMapper(rowMapper,statement);??
  257. ????????}??
  258. ????}??
  259. ??????
  260. ????/**?
  261. ?????*?按SQL查询对象列表,并将结果集封装成对象列表?
  262. [email protected]?
  263. [email protected],按名称绑定.?
  264. ?????*/??
  265. ????@SuppressWarnings("unchecked")??
  266. ????public?<X>?List<X>?findBySQLRowMapper(RowMapper<X>?rowMapper,final?String?sql,?final?Map<String,??>?values)?{??
  267. ????????Validate.notNull(rowMapper,?"rowMapper不能为空!");??
  268. ????????List<Object[]>?result?=?createSQLQuery(sql,?values).list();??
  269. ????????return?buildListResultFromRowMapper(rowMapper,?result);??
  270. ????}??
  271. ??
  272. ????/**?
  273. ?????*?按HQL查询唯一对象.?
  274. ?????*??
  275. [email protected],按顺序绑定.?
  276. ?????*/??
  277. ????@SuppressWarnings("unchecked")??
  278. ????public?<X>?X?findUniqueByHQL(final?String?hql,?final?Object...?values)?{??
  279. ????????return?(X)?createHQLQuery(hql,?values).uniqueResult();??
  280. ????}??
  281. ??????
  282. ????/**?
  283. ?????*?按SQL查询唯一对象.?
  284. ?????*??
  285. [email protected],按顺序绑定.?
  286. ?????*/??
  287. ????@SuppressWarnings("unchecked")??
  288. ????public?<X>?X?findUniqueBySQL(final?String?sql,?final?Object...?values)?{??
  289. ????????return?(X)?createSQLQuery(sql,?values).uniqueResult();??
  290. ????}??
  291. ??
  292. ????/**?
  293. ?????*?按HQL查询唯一对象.?
  294. ?????*??
  295. [email protected],按名称绑定.?
  296. ?????*/??
  297. ????@SuppressWarnings("unchecked")??
  298. ????public?<X>?X?findUniqueByHQL(final?String?hql,?final?Map<String,??>?values)?{??
  299. ????????return?(X)?createHQLQuery(hql,?values).uniqueResult();??
  300. ????}??
  301. ??????
  302. ????/**?
  303. ?????*?按HQL查询唯一对象.?
  304. [email protected]?
  305. [email protected],按名称绑定.?
  306. ?????*/??
  307. ????@SuppressWarnings("unchecked")??
  308. ????public?<X>?X?findUniqueBySQL(final?String?sql,?final?Map<String,??>?values)?{??
  309. ????????return?(X)?createSQLQuery(sql,?values).uniqueResult();??
  310. ????}??
  311. ??
  312. ????/**?
  313. ?????*?执行HQL进行批量修改/删除操作.?
  314. ?????*??
  315. [email protected],按顺序绑定.?
  316. [email protected]?
  317. ?????*/??
  318. ????public?int?batchExecuteHQL(final?String?hql,?final?Object...?values)?{??
  319. ????????return?createHQLQuery(hql,?values).executeUpdate();??
  320. ????}??
  321. ??????
  322. ????/**?
  323. ?????*?执行SQL进行批量修改/删除操作.?
  324. ?????*??
  325. [email protected]?
  326. [email protected],按顺序绑定.?
  327. [email protected]?
  328. ?????*/??
  329. ????public?int?batchExecuteSQL(final?String?sql,?final?Object...?values)?{??
  330. ????????return?createSQLQuery(sql,?values).executeUpdate();??
  331. ????}??
  332. ??
  333. ????/**?
  334. ?????*?执行HQL进行批量修改/删除操作.?
  335. ?????*??
  336. [email protected],按名称绑定.?
  337. [email protected]?
  338. ?????*/??
  339. ????public?int?batchExecuteHQL(final?String?hql,?final?Map<String,??>?values)?{??
  340. ????????return?createHQLQuery(hql,?values).executeUpdate();??
  341. ????}??
  342. ??????
  343. ????/**?
  344. ?????*?执行SQL进行批量修改/删除操作.?
  345. ?????*??
  346. [email protected],按名称绑定.?
  347. [email protected]?
  348. ?????*/??
  349. ????public?int?batchExecuteSQL(final?String?sql,?final?Map<String,??>?values)?{??
  350. ????????return?createSQLQuery(sql,?values).executeUpdate();??
  351. ????}??
  352. ??
  353. ????/**?
  354. ?????*?根据查询HQL与参数列表创建Query对象.?
  355. ?????*?与find()函数可进行更加灵活的操作.?
  356. ?????*??
  357. [email protected],按顺序绑定.?
  358. ?????*/??
  359. ????public?Query?createHQLQuery(final?String?queryString,?final?Object...?values)?{??
  360. ????????Query?query?=?getSession().createQuery(queryString);??
  361. ????????if?(values?!=?null)?{??
  362. ????????????for?(int?i?=?0;?i?<?values.length;?i++)?{??
  363. ????????????????query.setParameter(i,?values[i]);??
  364. ????????????}??
  365. ????????}??
  366. ????????return?query;??
  367. ????}??
  368. ??????
  369. ????/**?
  370. ?????*?根据查询SQL与参数列表创建Query对象.?
  371. ?????*?与find()函数可进行更加灵活的操作.?
  372. [email protected]?
  373. ?????*??
  374. [email protected],按顺序绑定.?
  375. ?????*/??
  376. ????public?Query?createSQLQuery(final?String?sqlQueryString,?final?Object...?values)?{??
  377. ????????Query?query?=?getSession().createSQLQuery(sqlQueryString);??
  378. ????????if?(values?!=?null)?{??
  379. ????????????for?(int?i?=?0;?i?<?values.length;?i++)?{??
  380. ????????????????query.setParameter(i,?values[i]);??
  381. ????????????}??
  382. ????????}??
  383. ????????return?query;??
  384. ????}??
  385. ??
  386. ????/**?
  387. ?????*?根据查询HQL与参数列表创建Query对象.?
  388. ?????*?与find()函数可进行更加灵活的操作.?
  389. ?????*??
  390. [email protected],按名称绑定.?
  391. ?????*/??
  392. ????public?Query?createHQLQuery(final?String?queryString,?final?Map<String,??>?values)?{??
  393. ????????Query?query?=?getSession().createQuery(queryString);??
  394. ????????if?(values?!=?null)?{??
  395. ????????????query.setProperties(values);??
  396. ????????}??
  397. ????????return?query;??
  398. ????}??
  399. ??????
  400. ????/**?
  401. ?????*?根据查询SQL与参数列表创建Query对象.?
  402. ?????*?与find()函数可进行更加灵活的操作.?
  403. [email protected]?
  404. [email protected],按名称绑定.?
  405. ?????*/??
  406. ????public?Query?createSQLQuery(final?String?queryString,?final?Map<String,??>?values)?{??
  407. ????????Query?query?=?getSession().createSQLQuery(queryString);??
  408. ????????if?(values?!=?null)?{??
  409. ????????????query.setProperties(values);??
  410. ????????}??
  411. ????????return?query;??
  412. ????}??
  413. ??
  414. ????/**?
  415. ?????*?按Criteria查询对象列表.?
  416. ?????*??
  417. [email protected]?
  418. ?????*/??
  419. ????@SuppressWarnings("unchecked")??
  420. ????public?List<T>?find(final?Criterion...?criterions)?{??
  421. ????????return?createCriteria(criterions).list();??
  422. ????}??
  423. ??
  424. ????/**?
  425. ?????*?按Criteria查询唯一对象.?
  426. ?????*??
  427. [email protected]?
  428. ?????*/??
  429. ????@SuppressWarnings("unchecked")??
  430. ????public?T?findUnique(final?Criterion...?criterions)?{??
  431. ????????return?(T)?createCriteria(criterions).uniqueResult();??
  432. ????}??
  433. ??
  434. ????/**?
  435. ?????*?根据Criterion条件创建Criteria.?
  436. ?????*?与find()函数可进行更加灵活的操作.?
  437. ?????*??
  438. [email protected]?
  439. ?????*/??
  440. ????public?Criteria?createCriteria(final?Criterion...?criterions)?{??
  441. ????????Criteria?criteria?=?getSession().createCriteria(entityClass);??
  442. ????????for?(Criterion?c?:?criterions)?{??
  443. ????????????criteria.add(c);??
  444. ????????}??
  445. ????????return?criteria;??
  446. ????}??
  447. ??
  448. ????/**?
  449. ?????*?初始化对象.?
  450. ?????*?使用load()方法得到的仅是对象Proxy,?在传到View层前需要进行初始化.?
  451. ?????*?如果传入entity,?则只初始化entity的直接属性,但不会初始化延迟加载的关联集合和属性.?
  452. ?????*?如需初始化关联属性,需执行:?
  453. ?????*?Hibernate.initialize(user.getRoles()),初始化User的直接属性和关联集合.?
  454. ?????*?Hibernate.initialize(user.getDescription()),初始化User的直接属性和延迟加载的Description属性.?
  455. ?????*/??
  456. ????public?void?initProxyObject(Object?proxy)?{??
  457. ????????Hibernate.initialize(proxy);??
  458. ????}??
  459. ??
  460. ????/**?
  461. ?????*?Flush当前Session.?
  462. ?????*/??
  463. ????public?void?flush()?{??
  464. ????????getSession().flush();??
  465. ????}??
  466. ??
  467. ????/**?
  468. ?????*?为Query添加distinct?transformer.?
  469. ?????*?预加载关联对象的HQL会引起主对象重复,?需要进行distinct处理.?
  470. ?????*/??
  471. ????public?Query?distinct(Query?query)?{??
  472. ????????query.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);??
  473. ????????return?query;??
  474. ????}??
  475. ??
  476. ????/**?
  477. ?????*?为Criteria添加distinct?transformer.?
  478. ?????*?预加载关联对象的HQL会引起主对象重复,?需要进行distinct处理.?
  479. ?????*/??
  480. ????public?Criteria?distinct(Criteria?criteria)?{??
  481. ????????criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);??
  482. ????????return?criteria;??
  483. ????}??
  484. ??
  485. ????/**?
  486. ?????*?取得对象的主键名.?
  487. ?????*/??
  488. ????public?String?getIdName()?{??
  489. ????????ClassMetadata?meta?=?getSessionFactory().getClassMetadata(entityClass);??
  490. ????????return?meta.getIdentifierPropertyName();??
  491. ????}??
  492. ??
  493. ????/**?
  494. ?????*?判断对象的属性值在数据库内是否唯一.?
  495. ?????*??
  496. ?????*?在修改对象的情景下,如果属性新修改的值(value)等于属性原来的值(orgValue)则不作比较.?
  497. ?????*/??
  498. ????public?boolean?isPropertyUnique(final?String?propertyName,?final?Object?newValue,?final?Object?oldValue)?{??
  499. ????????if?(newValue?==?null?||?newValue.equals(oldValue))?{??
  500. ????????????return?true;??
  501. ????????}??
  502. ????????Object?object?=?findUniqueBy(propertyName,?newValue);??
  503. ????????return?(object?==?null);??
  504. ????}??
  505. ??
  506. ????@Override??
  507. ????public?void?update(T?object)?{??
  508. ????????getSession().update(object);??
  509. ????}??
  510. ??
  511. ????@SuppressWarnings("unchecked")??
  512. ????@Override??
  513. ????public?T?load(ID?id)?{??
  514. ????????return?(T)?getSession().load(this.entityClass,?id);??
  515. ????}??
  516. ??????
  517. ????/**?
  518. ?????*?将list转化为数组?
  519. [email protected]?
  520. [email protected]?
  521. ?????*/??
  522. ????protected?Criterion[]?list2Array(List<Criterion>?list){??
  523. ????????if(list?==?null){??
  524. ????????????return?new?Criterion[0];??
  525. ????????}??
  526. ????????Criterion[]?result?=?new?Criterion[list.size()];??
  527. ????????for(int?i?=?0;?i?<?list.size();?i++){??
  528. ????????????result[i]?=?list.get(i);??
  529. ????????}??
  530. ????????return?result;??
  531. ????}??
  532. ??
  533. ????@Override??
  534. ????public?void?afterPropertiesSet()?throws?Exception?{??
  535. ????????templateCache?=?new?HashMap<String,?StatementTemplate>();??
  536. ????????if(this.dynamicStatementBuilder?==?null){??
  537. ????????????this.dynamicStatementBuilder?=?new?NoneDynamicHibernateStatementBuilder();??
  538. ????????}??
  539. ????????dynamicStatementBuilder.init();??
  540. ????????Map<String,String>?namedHQLQueries?=?dynamicStatementBuilder.getNamedHQLQueries();??
  541. ????????Map<String,String>?namedSQLQueries?=?dynamicStatementBuilder.getNamedSQLQueries();??
  542. ????????Configuration?configuration?=?new?Configuration();??
  543. ????????configuration.setNumberFormat("#");??
  544. ????????StringTemplateLoader?stringLoader?=?new?StringTemplateLoader();??
  545. ????????for(Entry<String,?String>?entry?:?namedHQLQueries.entrySet()){??
  546. ????????????stringLoader.putTemplate(entry.getKey(),?entry.getValue());??
  547. ????????????templateCache.put(entry.getKey(),?new?StatementTemplate(StatementTemplate.TYPE.HQL,new?Template(entry.getKey(),new?StringReader(entry.getValue()),configuration)));??
  548. ????????}??
  549. ????????for(Entry<String,?String>?entry?:?namedSQLQueries.entrySet()){??
  550. ????????????stringLoader.putTemplate(entry.getKey(),?entry.getValue());??
  551. ????????????templateCache.put(entry.getKey(),?new?StatementTemplate(StatementTemplate.TYPE.SQL,new?Template(entry.getKey(),new?StringReader(entry.getValue()),configuration)));??
  552. ????????}??
  553. ????????configuration.setTemplateLoader(stringLoader);??
  554. ????}??
  555. ??????
  556. ????protected?String?processTemplate(StatementTemplate?statementTemplate,Map<String,??>?parameters){??
  557. ????????StringWriter?stringWriter?=?new?StringWriter();??
  558. ????????try?{??
  559. ????????????statementTemplate.getTemplate().process(parameters,?stringWriter);??
  560. ????????}?catch?(Exception?e)?{??
  561. ????????????LOGER.error("处理DAO查询参数模板时发生错误:{}",e.toString());??
  562. ????????????throw?new?SysException(e);??
  563. ????????}??
  564. ????????return?stringWriter.toString();??
  565. ????}??
  566. }??

我们的SimpleHibernateDAO实现了InitializingBean,在其afterProperties方法中我们将调用DynamicHibernateStatementBuilder把语句缓存起来
上层方法调用示例-这个已经非常类似ibatis了

[java]?view plaincopyprint?
?
  1. public?List<Resource>?getDescendants(Long?userId,String?code)?{??
  2. ????Map<String,?Object>?values?=?new?HashMap<String,?Object>();??
  3. ????values.put("userId",?String.valueOf(userId));??
  4. ????values.put("code",?code);??
  5. ????values.put("type",?String.valueOf(ResourceTypeEnum.URL_RESOURCE.getType()));??
  6. ????values.put("status",?String.valueOf(ResourceStatusEnum.ACTIVE.getStatus()));??
  7. ????return?this.findByNamedQuery(new?ResourceRowMapper(),"resource.getDescendants",?values);??
  8. } ?
  相关解决方案