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语句的样例
- <?xml?version="1.0"?encoding="utf-8"?>??
- <!DOCTYPE?dynamic-hibernate-statement?PUBLIC?"-//Haier/HOP?Hibernate?Dynamic?Statement?DTD?1.0//EN"??
- "http://www.haier.com/dtd/dynamic-hibernate-statement-1.0.dtd">??
- <dynamic-hibernate-statement>??
- ????<!--?查询某个资源下的直接子节点?-->??
- ????<hql-query?name="resource.getChildren">??
- ????<![CDATA[?
- ????????from?Resource?where?parent.id=${parentId}?and?parent.id?!=?id?
- ????]]>???
- ????</hql-query>??
- ????<!--?查询系统中所有的root资源?-->??
- ????<hql-query?name="resource.getRoots">??
- ????<![CDATA[?
- ????????from?Resource?where?parent.id?=?id?order?by?orderIndex?
- ????]]>???
- ????</hql-query>??
- ????<!--?获取某个用户可访问的某个资源下的所有子资源?-->??
- ????<sql-query?name="resource.getDescendants">??
- ????<![CDATA[?
- ????????select?distinct?t.id,?
- ????????????????????????t.name,?
- ????????????????????????t.description,?
- ????????????????????????t.url,?
- ????????????????????????t.type,?
- ????????????????????????t.status,?
- ????????????????????????t.code,?
- ????????????????????????t.configuration,?
- ????????????????????????t.module_name,?
- ????????????????????????t.gmt_create,?
- ????????????????????????t.gmt_modified,?
- ????????????????????????t.create_by,?
- ????????????????????????t.last_modified_by,?
- ????????????????????????t.order_index,?
- ????????????????????????t.parent_id?
- ??????????from?resource_info?t?
- ?????????inner?join?role_resource?rr?
- ????????????on?t.id?=?rr.resource_id?
- ?????????inner?join?user_role?ur?
- ????????????on?rr.role_id?=?ur.role_id?
- ?????????where?ur.user_id?=?${userId}?
- ?????????<#if?type?==?'1'>?
- ????????????and?t.type=1?
- ????????????<#else>?
- ????????????and?t.type=0?
- ?????????</#if>?
- ???????????and?t.type?=??${type}?
- ???????????and?t.status?=??${status}?
- ?????????start?with?t.code?=?'${code}'?
- ????????connect?by?nocycle?prior?t.id?=?t.parent_id?
- ????]]>???
- ????</sql-query>??
- </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属性和传入查询参数来得到最终解析出来的语句
我们期望的方法可能是这样的:
- 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属性用来唯一标示该语句,如下
- <!--?HOP?Hibernate?Dynamic?Statement?Mapping?DTD.??
- ??
- <!DOCTYPE?dynamic-hibernate-statement?PUBLIC???
- ????"-//Haier/HOP?Hibernate?Dynamic?Statement?DTD?1.0//EN"??
- ????"http://www.haier.com/dtd/dynamic-hibernate-statement-1.0.dtd">??
- ??
- 这个文件时用来定义动态参数语句,类似itabis??
- ??
- -->??
- ??
- <!--?
- ????The?document?root.?
- ?-->??
- ??
- <!ELEMENT?dynamic-hibernate-statement?(??
- ????(hql-query|sql-query)*??
- )>??
- ????????????????????????????<!--?default:?none?-->??
- ??
- <!--?The?query?element?declares?a?named?Hibernate?query?string?-->??
- ??
- <!ELEMENT?hql-query?(#PCDATA)>??
- ????<!ATTLIST?hql-query?name?CDATA?#REQUIRED>??
- ??
- <!--?The?sql-query?element?declares?a?named?SQL?query?string?-->??
- ??
- <!ELEMENT?sql-query?(#PCDATA)>??
- ????<!ATTLIST?sql-query?name?CDATA?#REQUIRED>??
然后将其保存为dynamic-hibernate-statement-1.0.dtd,放在classpath下
编写DTD校验器
?
- /**?
- ?*?hibernate动态sql?dtd解析器?
- [email protected]?
- ?*?
- ?*/??
- public?class?DynamicStatementDTDEntityResolver?implements?EntityResolver,?Serializable{??
- ????private?static?final?long?serialVersionUID?=?8123799007554762965L;??
- ????private?static?final?Logger?LOGGER?=?LoggerFactory.getLogger(?DynamicStatementDTDEntityResolver.class?);??
- ????private?static?final?String?HOP_DYNAMIC_STATEMENT?=?"http://www.haier.com/dtd/";??
- ??
- ????public?InputSource?resolveEntity(String?publicId,?String?systemId)?{??
- ????????InputSource?source?=?null;?//?returning?null?triggers?default?behavior??
- ????????if?(?systemId?!=?null?)?{??
- ????????????LOGGER.debug(?"trying?to?resolve?system-id?["?+?systemId?+?"]"?);??
- ????????????if?(?systemId.startsWith(?HOP_DYNAMIC_STATEMENT?)?)?{??
- ????????????????LOGGER.debug(?"recognized?hop?dyanmic?statement?namespace;?attempting?to?resolve?on?classpath?under?com/haier/openplatform/dao/hibernate/"?);??
- ????????????????source?=?resolveOnClassPath(?publicId,?systemId,?HOP_DYNAMIC_STATEMENT?);??
- ????????????}??
- ????????}??
- ????????return?source;??
- ????}??
- ??
- ????private?InputSource?resolveOnClassPath(String?publicId,?String?systemId,?String?namespace)?{??
- ????????InputSource?source?=?null;??
- ????????String?path?=?"com/haier/openplatform/dao/hibernate/"?+?systemId.substring(?namespace.length()?);??
- ????????InputStream?dtdStream?=?resolveInHibernateNamespace(?path?);??
- ????????if?(?dtdStream?==?null?)?{??
- ????????????LOGGER.debug(?"unable?to?locate?["?+?systemId?+?"]?on?classpath"?);??
- ????????????if?(?systemId.substring(?namespace.length()?).indexOf(?"2.0"?)?>?-1?)?{??
- ????????????????LOGGER.error(?"Don't?use?old?DTDs,?read?the?Hibernate?3.x?Migration?Guide!"?);??
- ????????????}??
- ????????}??
- ????????else?{??
- ????????????LOGGER.debug(?"located?["?+?systemId?+?"]?in?classpath"?);??
- ????????????source?=?new?InputSource(?dtdStream?);??
- ????????????source.setPublicId(?publicId?);??
- ????????????source.setSystemId(?systemId?);??
- ????????}??
- ????????return?source;??
- ????}??
- ??
- ????protected?InputStream?resolveInHibernateNamespace(String?path)?{??
- ????????return?this.getClass().getClassLoader().getResourceAsStream(?path?);??
- ????}??
- ??
- ????protected?InputStream?resolveInLocalNamespace(String?path)?{??
- ????????try?{??
- ????????????return?ConfigHelper.getUserResourceAsStream(?path?);??
- ????????}??
- ????????catch?(?Throwable?t?)?{??
- ????????????return?null;??
- ????????}??
- ????}??
- }??
?
3.2编写sql文件
- <?xml?version="1.0"?encoding="utf-8"?>??
- <!DOCTYPE?dynamic-hibernate-statement?PUBLIC?"-//Haier/HOP?Hibernate?Dynamic?Statement?DTD?1.0//EN"??
- "http://www.haier.com/dtd/dynamic-hibernate-statement-1.0.dtd">??
- <dynamic-hibernate-statement>??
- ????<!--?查询某个资源下的直接子节点?-->??
- ????<hql-query?name="resource.getChildren">??
- ????<![CDATA[?
- ????????from?Resource?where?parent.id=${parentId}?and?parent.id?!=?id?
- ????]]>???
- ????</hql-query>??
- ????<!--?查询系统中所有的root资源?-->??
- ????<hql-query?name="resource.getRoots">??
- ????<![CDATA[?
- ????????from?Resource?where?parent.id?=?id?order?by?orderIndex?
- ????]]>???
- ????</hql-query>??
- ????<!--?获取某个用户可访问的某个资源下的所有子资源?-->??
- ????<sql-query?name="resource.getDescendants">??
- ????<![CDATA[?
- ????????select?distinct?t.id,?
- ????????????????????????t.name,?
- ????????????????????????t.description,?
- ????????????????????????t.url,?
- ????????????????????????t.type,?
- ????????????????????????t.status,?
- ????????????????????????t.code,?
- ????????????????????????t.configuration,?
- ????????????????????????t.module_name,?
- ????????????????????????t.gmt_create,?
- ????????????????????????t.gmt_modified,?
- ????????????????????????t.create_by,?
- ????????????????????????t.last_modified_by,?
- ????????????????????????t.order_index,?
- ????????????????????????t.parent_id?
- ??????????from?resource_info?t?
- ?????????inner?join?role_resource?rr?
- ????????????on?t.id?=?rr.resource_id?
- ?????????inner?join?user_role?ur?
- ????????????on?rr.role_id?=?ur.role_id?
- ?????????where?ur.user_id?=?${userId}?
- ?????????<#if?type?==?'1'>?
- ????????????and?t.type=1?
- ????????????<#else>?
- ????????????and?t.type=0?
- ?????????</#if>?
- ???????????and?t.type?=??${type}?
- ???????????and?t.status?=??${status}?
- ?????????start?with?t.code?=?'${code}'?
- ????????connect?by?nocycle?prior?t.id?=?t.parent_id?
- ????]]>???
- ????</sql-query>??
- </dynamic-hibernate-statement>??
3.3加载动态sql文件
这里我们将加载sql/hql语句的程序独立到一个单独的类中,以便独立扩展
这里一共3个方法,分表标示获取系统中sql/hql语句的map(key:语句名称,value:具体的)
- /**?
- ?*?动态sql/hql语句组装器?
- [email protected]?
- ?*?
- ?*/??
- public?interface?DynamicHibernateStatementBuilder?{??
- ????/**?
- ?????*?hql语句map?
- [email protected]?
- ?????*/??
- ????public?Map<String,String>?getNamedHQLQueries();??
- ????/**?
- ?????*?sql语句map?
- [email protected]?
- ?????*/??
- ????public?Map<String,String>?getNamedSQLQueries();??
- ????/**?
- ?????*?初始化?
- [email protected]?
- ?????*/??
- ????public?void?init()?throws?IOException;??
- }??
默认的加载器-将指定配置文件中的sql/hql语句加载到内存中
- /**?
- [email protected]?
- ?*?
- ?*/??
- public?class?DefaultDynamicHibernateStatementBuilder?implements?DynamicHibernateStatementBuilder,?ResourceLoaderAware?{??
- ????private?static?final?Logger?LOGGER?=?LoggerFactory.getLogger(DefaultDynamicHibernateStatementBuilder.class);??
- ????private?Map<String,?String>?namedHQLQueries;??
- ????private?Map<String,?String>?namedSQLQueries;??
- ????private?String[]?fileNames?=?new?String[0];??
- ????private?ResourceLoader?resourceLoader;??
- ????private?EntityResolver?entityResolver?=?new?DynamicStatementDTDEntityResolver();??
- ????/**?
- ?????*?查询语句名称缓存,不允许重复?
- ?????*/??
- ????private?Set<String>?nameCache?=?new?HashSet<String>();??
- ??
- ????public?void?setFileNames(String[]?fileNames)?{??
- ????????this.fileNames?=?fileNames;??
- ????}??
- ??
- ????@Override??
- ????public?Map<String,?String>?getNamedHQLQueries()?{??
- ????????return?namedHQLQueries;??
- ????}??
- ??
- ????@Override??
- ????public?Map<String,?String>?getNamedSQLQueries()?{??
- ????????return?namedSQLQueries;??
- ????}??
- ??
- ????@Override??
- ????public?void?init()?throws?IOException?{??
- ????????namedHQLQueries?=?new?HashMap<String,?String>();??
- ????????namedSQLQueries?=?new?HashMap<String,?String>();??
- ????????boolean?flag?=?this.resourceLoader?instanceof?ResourcePatternResolver;??
- ????????for?(String?file?:?fileNames)?{??
- ????????????if?(flag)?{??
- ????????????????Resource[]?resources?=?((ResourcePatternResolver)?this.resourceLoader).getResources(file);??
- ????????????????buildMap(resources);??
- ????????????}?else?{??
- ????????????????Resource?resource?=?resourceLoader.getResource(file);??
- ????????????????buildMap(resource);??
- ????????????}??
- ????????}??
- ????????//clear?name?cache??
- ????????nameCache.clear();??
- ????}??
- ??
- ????@Override??
- ????public?void?setResourceLoader(ResourceLoader?resourceLoader)?{??
- ????????this.resourceLoader?=?resourceLoader;??
- ????}??
- ??
- ????private?void?buildMap(Resource[]?resources)?throws?IOException?{??
- ????????if?(resources?==?null)?{??
- ????????????return;??
- ????????}??
- ????????for?(Resource?resource?:?resources)?{??
- ????????????buildMap(resource);??
- ????????}??
- ????}??
- ??
- ????@SuppressWarnings({?"rawtypes"?})??
- ????private?void?buildMap(Resource?resource)?{??
- ????????InputSource?inputSource?=?null;??
- ????????try?{??
- ????????????inputSource?=?new?InputSource(resource.getInputStream());??
- ????????????XmlDocument?metadataXml?=?MappingReader.INSTANCE.readMappingDocument(entityResolver,?inputSource,??
- ????????????????????new?OriginImpl("file",?resource.getFilename()));??
- ????????????if?(isDynamicStatementXml(metadataXml))?{??
- ????????????????final?Document?doc?=?metadataXml.getDocumentTree();??
- ????????????????final?Element?dynamicHibernateStatement?=?doc.getRootElement();??
- ????????????????Iterator?rootChildren?=?dynamicHibernateStatement.elementIterator();??
- ????????????????while?(rootChildren.hasNext())?{??
- ????????????????????final?Element?element?=?(Element)?rootChildren.next();??
- ????????????????????final?String?elementName?=?element.getName();??
- ????????????????????if?("sql-query".equals(elementName))?{??
- ????????????????????????putStatementToCacheMap(resource,?element,?namedSQLQueries);??
- ????????????????????}?else?if?("hql-query".equals(elementName))?{??
- ????????????????????????putStatementToCacheMap(resource,?element,?namedHQLQueries);??
- ????????????????????}??
- ????????????????}??
- ????????????}??
- ????????}?catch?(Exception?e)?{??
- ????????????LOGGER.error(e.toString());??
- ????????????throw?new?SysException(e);??
- ????????}?finally?{??
- ????????????if?(inputSource?!=?null?&&?inputSource.getByteStream()?!=?null)?{??
- ????????????????try?{??
- ????????????????????inputSource.getByteStream().close();??
- ????????????????}?catch?(IOException?e)?{??
- ????????????????????LOGGER.error(e.toString());??
- ????????????????????throw?new?SysException(e);??
- ????????????????}??
- ????????????}??
- ????????}??
- ??
- ????}??
- ??
- ????private?void?putStatementToCacheMap(Resource?resource,?final?Element?element,?Map<String,?String>?statementMap)??
- ????????????throws?IOException?{??
- ????????String?sqlQueryName?=?element.attribute("name").getText();??
- ????????Validate.notEmpty(sqlQueryName);??
- ????????if?(nameCache.contains(sqlQueryName))?{??
- ????????????throw?new?SysException("重复的sql-query/hql-query语句定义在文件:"?+?resource.getURI()?+?"中,必须保证name的唯一.");??
- ????????}??
- ????????nameCache.add(sqlQueryName);??
- ????????String?queryText?=?element.getText();??
- ????????statementMap.put(sqlQueryName,?queryText);??
- ????}??
- ??
- ????private?static?boolean?isDynamicStatementXml(XmlDocument?xmlDocument)?{??
- ????????return?"dynamic-hibernate-statement".equals(xmlDocument.getDocumentTree().getRootElement().getName());??
- ????}??
- }??
配置一下
- ????<bean?id="dynamicStatementBuilder"?class="com.haier.openplatform.dao.hibernate.support.DefaultDynamicHibernateStatementBuilder">??
- ????????<property?name="fileNames">??
- ????????????<list>??
- ????????????????<value>classpath*:/**/*-dynamic.xml</value><!--这里我们指定要加载某个文件夹下所有以-dynamic.xml结尾的文件?-->??
- ????????????</list>??
- ????????</property>??
- ????</bean>??
- ????<bean?id="baseHibernateDAO"?class="com.haier.openplatform.dao.hibernate.BaseDAOHibernateImpl"?abstract="true">??
- ????????<property?name="sessionFactory">??
- ????????????<ref?bean="sessionFactory"/>??
- ????????</property>??
- ????????<property?name="dynamicStatementBuilder"?ref="dynamicStatementBuilder"/>??
- ????</bean>??
dao层代码
- /**?
- ?*?Hibernate实现的DAO层?
- [email protected]<T>?DAO操作的对象类型?
- [email protected]<ID>?主键类型?
- [email protected]?
- ?*?
- ?*/??
- public?class?SimpleHibernateDAO<T,ID?extends?Serializable>?implements?BaseDAO<T,?ID>,InitializingBean{??
- ????private?static?final?Logger?LOGER?=?LoggerFactory.getLogger(SimpleHibernateDAO.class);??
- ????protected?SessionFactory?sessionFactory;??
- ????protected?Class<T>?entityClass;??
- ????/**?
- ?????*?模板缓存?
- ?????*/??
- ????protected?Map<String,?StatementTemplate>?templateCache;??
- ????protected?DynamicHibernateStatementBuilder?dynamicStatementBuilder;??
- ????/**?
- ?????*?通过子类的泛型定义取得对象类型Class.?
- ?????*?eg.?
- ?????*?public?class?UserDao?extends?SimpleHibernateDao<User,?Long>?
- ?????*/??
- ????public?SimpleHibernateDAO()?{??
- ????????this.entityClass?=?Reflections.getSuperClassGenricType(getClass());??
- ????}??
- ??
- ????/**?
- ?????*?取得sessionFactory.?
- ?????*/??
- ????public?SessionFactory?getSessionFactory()?{??
- ????????return?sessionFactory;??
- ????}??
- ??
- ????/**?
- [email protected],?当有多个SesionFactory的时候在子类重载本函数.?
- ?????*/??
- ????public?void?setSessionFactory(final?SessionFactory?sessionFactory)?{??
- ????????this.sessionFactory?=?sessionFactory;??
- ????}??
- ??
- ????public?void?setDynamicStatementBuilder(DynamicHibernateStatementBuilder?dynamicStatementBuilder)?{??
- ????????this.dynamicStatementBuilder?=?dynamicStatementBuilder;??
- ????}??
- ??
- ????/**?
- ?????*?取得当前Session.?
- ?????*/??
- ????public?Session?getSession()?{??
- ????????return?sessionFactory.getCurrentSession();??
- ????}??
- ??
- ????/**?
- ?????*?保存新增或修改的对象.?
- ?????*/??
- ????@Override??
- ????public?void?save(final?T?entity)?{??
- ????????Validate.notNull(entity,?"entity不能为空");??
- ????????getSession().save(entity);??
- ????????LOGER.debug("save?entity:?{}",?entity);??
- ????}??
- ??
- ????/**?
- ?????*?删除对象.?
- ?????*??
- [email protected]?含id属性的transient对象.?
- ?????*/??
- ????@Override??
- ????public?void?delete(final?T?entity)?{??
- ????????if(entity?==?null){??
- ????????????return;??
- ????????}??
- ????????getSession().delete(entity);??
- ????????LOGER.debug("delete?entity:?{}",?entity);??
- ????}??
- ??
- ????/**?
- ?????*?按id删除对象.?
- ?????*/??
- ????@Override??
- ????public?void?delete(final?ID?id)?{??
- ????????Validate.notNull(id,?"id不能为空");??
- ????????delete(get(id));??
- ????????LOGER.debug("delete?entity?{},id?is?{}",?entityClass.getSimpleName(),?id);??
- ????}??
- ??
- ????/**?
- ?????*?按id获取对象.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????@Override??
- ????public?T?get(final?ID?id)?{??
- ????????Validate.notNull(id,?"id不能为空");??
- ????????return?(T)?getSession().get(entityClass,?id);??
- ????}??
- ??
- ????/**?
- ?????*?按id列表获取对象列表.?
- ?????*/??
- ????public?List<T>?get(final?Collection<ID>?ids)?{??
- ????????return?find(Restrictions.in(getIdName(),?ids));??
- ????}??
- ??
- ????/**?
- ?????*??获取全部对象.?
- ?????*/??
- ????@Override??
- ????public?List<T>?getAll()?{??
- ????????return?find();??
- ????}??
- ??
- ????/**?
- ?????*??获取全部对象,?支持按属性行序.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?List<T>?getAll(String?orderByProperty,?boolean?isAsc)?{??
- ????????Criteria?c?=?createCriteria();??
- ????????if?(isAsc)?{??
- ????????????c.addOrder(Order.asc(orderByProperty));??
- ????????}?else?{??
- ????????????c.addOrder(Order.desc(orderByProperty));??
- ????????}??
- ????????return?c.list();??
- ????}??
- ??
- ????/**?
- ?????*?按属性查找对象列表,?匹配方式为相等.?
- ?????*/??
- ????public?List<T>?findBy(final?String?propertyName,?final?Object?value)?{??
- ????????Criterion?criterion?=?Restrictions.eq(propertyName,?value);??
- ????????return?find(criterion);??
- ????}??
- ??
- ????/**?
- ?????*?按属性查找唯一对象,?匹配方式为相等.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????@Override??
- ????public?T?findUniqueBy(final?String?propertyName,?final?Object?value)?{??
- ????????Criterion?criterion?=?Restrictions.eq(propertyName,?value);??
- ????????return?((T)?createCriteria(criterion).uniqueResult());??
- ????}??
- ??
- ????/**?
- ?????*?按HQL查询对象列表.?
- ?????*??
- [email protected],按顺序绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?List<X>?findByHQL(final?String?hql,?final?Object...?values)?{??
- ????????return?createHQLQuery(hql,?values).list();??
- ????}??
- ??????
- ????/**?
- ?????*?按HQL查询对象列表,并将对象封装成指定的对象?
- ?????*??
- [email protected],按顺序绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?List<X>?findByHQLRowMapper(RowMapper<X>?rowMapper,final?String?hql,?final?Object...?values)?{??
- ????????Validate.notNull(rowMapper,?"rowMapper不能为空!");??
- ????????List<Object[]>?result?=?createHQLQuery(hql,?values).list();??
- ????????return?buildListResultFromRowMapper(rowMapper,?result);??
- ????}??
- ??
- ????protected?<X>?List<X>?buildListResultFromRowMapper(RowMapper<X>?rowMapper,?List<Object[]>?result)?{??
- ????????List<X>?rs?=?new?ArrayList<X>(result.size());??
- ????????for(Object[]?obj?:?result){??
- ????????????rs.add(rowMapper.fromColumn(obj));??
- ????????}??
- ????????return?rs;??
- ????}??
- ??????
- ??????
- ????/**?
- ?????*?按SQL查询对象列表.?
- ?????*??
- [email protected],按顺序绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?List<X>?findBySQLRowMapper(RowMapper<X>?rowMapper,final?String?sql,?final?Object...?values)?{??
- ????????Validate.notNull(rowMapper,?"rowMapper不能为空!");??
- ????????List<Object[]>?result?=?createSQLQuery(sql,?values).list();??
- ????????return?buildListResultFromRowMapper(rowMapper,?result);??
- ????}??
- ??????
- ????/**?
- ?????*?按SQL查询对象列表,并将结果集转换成指定的对象列表?
- ?????*??
- [email protected],按顺序绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?List<X>?findBySQL(final?String?sql,?final?Object...?values)?{??
- ????????return?createSQLQuery(sql,?values).list();??
- ????}??
- ??
- ????/**?
- ?????*?按HQL查询对象列表.?
- ?????*??
- [email protected],按名称绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?List<X>?findByHQL(final?String?hql,?final?Map<String,??>?values)?{??
- ????????return?createHQLQuery(hql,?values).list();??
- ????}??
- ??????
- ????/**?
- ?????*?按HQL查询对象列表,并将结果集封装成对象列表?
- ?????*??
- [email protected],按名称绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?List<X>?findByHQLRowMapper(RowMapper<X>?rowMapper,final?String?hql,?final?Map<String,??>?values)?{??
- ????????Validate.notNull(rowMapper,?"rowMapper不能为空!");??
- ????????List<Object[]>?result?=?createHQLQuery(hql,?values).list();??
- ????????return?buildListResultFromRowMapper(rowMapper,?result);??
- ????}??
- ??????
- ????/**?
- ?????*?按SQL查询对象列表.?
- [email protected]?
- [email protected],按名称绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?List<X>?findBySQL(final?String?sql,?final?Map<String,??>?values)?{??
- ????????return?createSQLQuery(sql,?values).list();??
- ????}??
- ??????
- ????/**?
- ?????*?查询在xxx.hbm.xml中配置的查询语句?
- [email protected]?
- [email protected]?
- [email protected]?
- ?????*/??
- ????public?<X>?List<X>?findByNamedQuery(final?String?queryName,?final?Map<String,??>?parameters)?{??
- ????????StatementTemplate?statementTemplate?=?templateCache.get(queryName);??
- ????????String?statement?=?processTemplate(statementTemplate,parameters);??
- ????????if(statementTemplate.getType()?==?StatementTemplate.TYPE.HQL){??
- ????????????return?this.findByHQL(statement);??
- ????????}else{??
- ????????????return?this.findBySQL(statement);??
- ????????}??
- ????}??
- ??????
- ????/**?
- ?????*?查询在xxx.hbm.xml中配置的查询语句?
- [email protected]?
- [email protected]?
- [email protected]?
- [email protected]?
- ?????*/??
- ????public?<X>?List<X>?findByNamedQuery(RowMapper<X>?rowMapper,final?String?queryName,?final?Map<String,??>?parameters)?{??
- ????????StatementTemplate?statementTemplate?=?templateCache.get(queryName);??
- ????????String?statement?=?processTemplate(statementTemplate,parameters);??
- ????????if(statementTemplate.getType()?==?StatementTemplate.TYPE.HQL){??
- ????????????return?this.findByHQLRowMapper(rowMapper,statement);??
- ????????}else{??
- ????????????return?this.findBySQLRowMapper(rowMapper,statement);??
- ????????}??
- ????}??
- ??????
- ????/**?
- ?????*?按SQL查询对象列表,并将结果集封装成对象列表?
- [email protected]?
- [email protected],按名称绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?List<X>?findBySQLRowMapper(RowMapper<X>?rowMapper,final?String?sql,?final?Map<String,??>?values)?{??
- ????????Validate.notNull(rowMapper,?"rowMapper不能为空!");??
- ????????List<Object[]>?result?=?createSQLQuery(sql,?values).list();??
- ????????return?buildListResultFromRowMapper(rowMapper,?result);??
- ????}??
- ??
- ????/**?
- ?????*?按HQL查询唯一对象.?
- ?????*??
- [email protected],按顺序绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?X?findUniqueByHQL(final?String?hql,?final?Object...?values)?{??
- ????????return?(X)?createHQLQuery(hql,?values).uniqueResult();??
- ????}??
- ??????
- ????/**?
- ?????*?按SQL查询唯一对象.?
- ?????*??
- [email protected],按顺序绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?X?findUniqueBySQL(final?String?sql,?final?Object...?values)?{??
- ????????return?(X)?createSQLQuery(sql,?values).uniqueResult();??
- ????}??
- ??
- ????/**?
- ?????*?按HQL查询唯一对象.?
- ?????*??
- [email protected],按名称绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?X?findUniqueByHQL(final?String?hql,?final?Map<String,??>?values)?{??
- ????????return?(X)?createHQLQuery(hql,?values).uniqueResult();??
- ????}??
- ??????
- ????/**?
- ?????*?按HQL查询唯一对象.?
- [email protected]?
- [email protected],按名称绑定.?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?<X>?X?findUniqueBySQL(final?String?sql,?final?Map<String,??>?values)?{??
- ????????return?(X)?createSQLQuery(sql,?values).uniqueResult();??
- ????}??
- ??
- ????/**?
- ?????*?执行HQL进行批量修改/删除操作.?
- ?????*??
- [email protected],按顺序绑定.?
- [email protected]?
- ?????*/??
- ????public?int?batchExecuteHQL(final?String?hql,?final?Object...?values)?{??
- ????????return?createHQLQuery(hql,?values).executeUpdate();??
- ????}??
- ??????
- ????/**?
- ?????*?执行SQL进行批量修改/删除操作.?
- ?????*??
- [email protected]?
- [email protected],按顺序绑定.?
- [email protected]?
- ?????*/??
- ????public?int?batchExecuteSQL(final?String?sql,?final?Object...?values)?{??
- ????????return?createSQLQuery(sql,?values).executeUpdate();??
- ????}??
- ??
- ????/**?
- ?????*?执行HQL进行批量修改/删除操作.?
- ?????*??
- [email protected],按名称绑定.?
- [email protected]?
- ?????*/??
- ????public?int?batchExecuteHQL(final?String?hql,?final?Map<String,??>?values)?{??
- ????????return?createHQLQuery(hql,?values).executeUpdate();??
- ????}??
- ??????
- ????/**?
- ?????*?执行SQL进行批量修改/删除操作.?
- ?????*??
- [email protected],按名称绑定.?
- [email protected]?
- ?????*/??
- ????public?int?batchExecuteSQL(final?String?sql,?final?Map<String,??>?values)?{??
- ????????return?createSQLQuery(sql,?values).executeUpdate();??
- ????}??
- ??
- ????/**?
- ?????*?根据查询HQL与参数列表创建Query对象.?
- ?????*?与find()函数可进行更加灵活的操作.?
- ?????*??
- [email protected],按顺序绑定.?
- ?????*/??
- ????public?Query?createHQLQuery(final?String?queryString,?final?Object...?values)?{??
- ????????Query?query?=?getSession().createQuery(queryString);??
- ????????if?(values?!=?null)?{??
- ????????????for?(int?i?=?0;?i?<?values.length;?i++)?{??
- ????????????????query.setParameter(i,?values[i]);??
- ????????????}??
- ????????}??
- ????????return?query;??
- ????}??
- ??????
- ????/**?
- ?????*?根据查询SQL与参数列表创建Query对象.?
- ?????*?与find()函数可进行更加灵活的操作.?
- [email protected]?
- ?????*??
- [email protected],按顺序绑定.?
- ?????*/??
- ????public?Query?createSQLQuery(final?String?sqlQueryString,?final?Object...?values)?{??
- ????????Query?query?=?getSession().createSQLQuery(sqlQueryString);??
- ????????if?(values?!=?null)?{??
- ????????????for?(int?i?=?0;?i?<?values.length;?i++)?{??
- ????????????????query.setParameter(i,?values[i]);??
- ????????????}??
- ????????}??
- ????????return?query;??
- ????}??
- ??
- ????/**?
- ?????*?根据查询HQL与参数列表创建Query对象.?
- ?????*?与find()函数可进行更加灵活的操作.?
- ?????*??
- [email protected],按名称绑定.?
- ?????*/??
- ????public?Query?createHQLQuery(final?String?queryString,?final?Map<String,??>?values)?{??
- ????????Query?query?=?getSession().createQuery(queryString);??
- ????????if?(values?!=?null)?{??
- ????????????query.setProperties(values);??
- ????????}??
- ????????return?query;??
- ????}??
- ??????
- ????/**?
- ?????*?根据查询SQL与参数列表创建Query对象.?
- ?????*?与find()函数可进行更加灵活的操作.?
- [email protected]?
- [email protected],按名称绑定.?
- ?????*/??
- ????public?Query?createSQLQuery(final?String?queryString,?final?Map<String,??>?values)?{??
- ????????Query?query?=?getSession().createSQLQuery(queryString);??
- ????????if?(values?!=?null)?{??
- ????????????query.setProperties(values);??
- ????????}??
- ????????return?query;??
- ????}??
- ??
- ????/**?
- ?????*?按Criteria查询对象列表.?
- ?????*??
- [email protected]?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?List<T>?find(final?Criterion...?criterions)?{??
- ????????return?createCriteria(criterions).list();??
- ????}??
- ??
- ????/**?
- ?????*?按Criteria查询唯一对象.?
- ?????*??
- [email protected]?
- ?????*/??
- ????@SuppressWarnings("unchecked")??
- ????public?T?findUnique(final?Criterion...?criterions)?{??
- ????????return?(T)?createCriteria(criterions).uniqueResult();??
- ????}??
- ??
- ????/**?
- ?????*?根据Criterion条件创建Criteria.?
- ?????*?与find()函数可进行更加灵活的操作.?
- ?????*??
- [email protected]?
- ?????*/??
- ????public?Criteria?createCriteria(final?Criterion...?criterions)?{??
- ????????Criteria?criteria?=?getSession().createCriteria(entityClass);??
- ????????for?(Criterion?c?:?criterions)?{??
- ????????????criteria.add(c);??
- ????????}??
- ????????return?criteria;??
- ????}??
- ??
- ????/**?
- ?????*?初始化对象.?
- ?????*?使用load()方法得到的仅是对象Proxy,?在传到View层前需要进行初始化.?
- ?????*?如果传入entity,?则只初始化entity的直接属性,但不会初始化延迟加载的关联集合和属性.?
- ?????*?如需初始化关联属性,需执行:?
- ?????*?Hibernate.initialize(user.getRoles()),初始化User的直接属性和关联集合.?
- ?????*?Hibernate.initialize(user.getDescription()),初始化User的直接属性和延迟加载的Description属性.?
- ?????*/??
- ????public?void?initProxyObject(Object?proxy)?{??
- ????????Hibernate.initialize(proxy);??
- ????}??
- ??
- ????/**?
- ?????*?Flush当前Session.?
- ?????*/??
- ????public?void?flush()?{??
- ????????getSession().flush();??
- ????}??
- ??
- ????/**?
- ?????*?为Query添加distinct?transformer.?
- ?????*?预加载关联对象的HQL会引起主对象重复,?需要进行distinct处理.?
- ?????*/??
- ????public?Query?distinct(Query?query)?{??
- ????????query.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);??
- ????????return?query;??
- ????}??
- ??
- ????/**?
- ?????*?为Criteria添加distinct?transformer.?
- ?????*?预加载关联对象的HQL会引起主对象重复,?需要进行distinct处理.?
- ?????*/??
- ????public?Criteria?distinct(Criteria?criteria)?{??
- ????????criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);??
- ????????return?criteria;??
- ????}??
- ??
- ????/**?
- ?????*?取得对象的主键名.?
- ?????*/??
- ????public?String?getIdName()?{??
- ????????ClassMetadata?meta?=?getSessionFactory().getClassMetadata(entityClass);??
- ????????return?meta.getIdentifierPropertyName();??
- ????}??
- ??
- ????/**?
- ?????*?判断对象的属性值在数据库内是否唯一.?
- ?????*??
- ?????*?在修改对象的情景下,如果属性新修改的值(value)等于属性原来的值(orgValue)则不作比较.?
- ?????*/??
- ????public?boolean?isPropertyUnique(final?String?propertyName,?final?Object?newValue,?final?Object?oldValue)?{??
- ????????if?(newValue?==?null?||?newValue.equals(oldValue))?{??
- ????????????return?true;??
- ????????}??
- ????????Object?object?=?findUniqueBy(propertyName,?newValue);??
- ????????return?(object?==?null);??
- ????}??
- ??
- ????@Override??
- ????public?void?update(T?object)?{??
- ????????getSession().update(object);??
- ????}??
- ??
- ????@SuppressWarnings("unchecked")??
- ????@Override??
- ????public?T?load(ID?id)?{??
- ????????return?(T)?getSession().load(this.entityClass,?id);??
- ????}??
- ??????
- ????/**?
- ?????*?将list转化为数组?
- [email protected]?
- [email protected]?
- ?????*/??
- ????protected?Criterion[]?list2Array(List<Criterion>?list){??
- ????????if(list?==?null){??
- ????????????return?new?Criterion[0];??
- ????????}??
- ????????Criterion[]?result?=?new?Criterion[list.size()];??
- ????????for(int?i?=?0;?i?<?list.size();?i++){??
- ????????????result[i]?=?list.get(i);??
- ????????}??
- ????????return?result;??
- ????}??
- ??
- ????@Override??
- ????public?void?afterPropertiesSet()?throws?Exception?{??
- ????????templateCache?=?new?HashMap<String,?StatementTemplate>();??
- ????????if(this.dynamicStatementBuilder?==?null){??
- ????????????this.dynamicStatementBuilder?=?new?NoneDynamicHibernateStatementBuilder();??
- ????????}??
- ????????dynamicStatementBuilder.init();??
- ????????Map<String,String>?namedHQLQueries?=?dynamicStatementBuilder.getNamedHQLQueries();??
- ????????Map<String,String>?namedSQLQueries?=?dynamicStatementBuilder.getNamedSQLQueries();??
- ????????Configuration?configuration?=?new?Configuration();??
- ????????configuration.setNumberFormat("#");??
- ????????StringTemplateLoader?stringLoader?=?new?StringTemplateLoader();??
- ????????for(Entry<String,?String>?entry?:?namedHQLQueries.entrySet()){??
- ????????????stringLoader.putTemplate(entry.getKey(),?entry.getValue());??
- ????????????templateCache.put(entry.getKey(),?new?StatementTemplate(StatementTemplate.TYPE.HQL,new?Template(entry.getKey(),new?StringReader(entry.getValue()),configuration)));??
- ????????}??
- ????????for(Entry<String,?String>?entry?:?namedSQLQueries.entrySet()){??
- ????????????stringLoader.putTemplate(entry.getKey(),?entry.getValue());??
- ????????????templateCache.put(entry.getKey(),?new?StatementTemplate(StatementTemplate.TYPE.SQL,new?Template(entry.getKey(),new?StringReader(entry.getValue()),configuration)));??
- ????????}??
- ????????configuration.setTemplateLoader(stringLoader);??
- ????}??
- ??????
- ????protected?String?processTemplate(StatementTemplate?statementTemplate,Map<String,??>?parameters){??
- ????????StringWriter?stringWriter?=?new?StringWriter();??
- ????????try?{??
- ????????????statementTemplate.getTemplate().process(parameters,?stringWriter);??
- ????????}?catch?(Exception?e)?{??
- ????????????LOGER.error("处理DAO查询参数模板时发生错误:{}",e.toString());??
- ????????????throw?new?SysException(e);??
- ????????}??
- ????????return?stringWriter.toString();??
- ????}??
- }??
我们的SimpleHibernateDAO实现了InitializingBean,在其afterProperties方法中我们将调用DynamicHibernateStatementBuilder把语句缓存起来
上层方法调用示例-这个已经非常类似ibatis了
- public?List<Resource>?getDescendants(Long?userId,String?code)?{??
- ????Map<String,?Object>?values?=?new?HashMap<String,?Object>();??
- ????values.put("userId",?String.valueOf(userId));??
- ????values.put("code",?code);??
- ????values.put("type",?String.valueOf(ResourceTypeEnum.URL_RESOURCE.getType()));??
- ????values.put("status",?String.valueOf(ResourceStatusEnum.ACTIVE.getStatus()));??
- ????return?this.findByNamedQuery(new?ResourceRowMapper(),"resource.getDescendants",?values);??
- } ?