第一次写博客。文章有点渣,喜欢就看看,不喜欢路过点个赞。

    效果:直接一条语句多种用法

  1.     FROM User A
  2.    WHERE
  3.    1=1
  4.    <#if id??>
  5.       <#if like??>
  6.          and A.id like '%'||:id||'%'
  7.       <#else>
  8.          and A.id=:id
  9.       </#if>
  10.    </#if>

    先来原理 HQL/SQL + Freemarker 模版生成查询语句。

    1:把SQL/HQL写在XML。

    2:编写文件扫描器(缺)

    3:读取解释XML

    4:按实体类空间缓存查询语句

    5:直接使用

注意:不要直接复制,先弄懂流程,因为这源于旧版本及测试包来写的,也省略了部分代码,因此包路径有问题。程序也不完整,缺了的自己让大家自己去思考实现。基本上依赖Spring,不依赖Spring注入的可以考虑用代理模式注入(反射/生成字节码(javassist/asm)/CGLIB等)

1:为了方便先定义约束Query.dtd

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!ELEMENT QueryList (Alias*,Query*)>
  3. <!--<!ELEMENT Context (CachePool,Bean*,Intercept*,ScanToPack*,CloneModel)>-->
  4. <!ELEMENT Alias EMPTY><!--别名-->
  5. <!ELEMENT Query (#PCDATA)><!--sql/hql-->
  6.  
  7. <!--QueryList-->
  8. <!ATTLIST QueryList package CDATA #REQUIRED>
  9. <!--Alias-->
  10. <!ATTLIST Alias name CDATA #REQUIRED><!--实体类全名-->
  11. <!ATTLIST Alias Alias CDATA #REQUIRED><!--SQL/HQL 语句中的实体类别名-->
  12. <!--Query-->
  13. <!ATTLIST Query name CDATA #REQUIRED><!--实体类全名-->
  14. <!ATTLIST Query type (HQL|SQL) #REQUIRED><!--语句类型:HQL/SQL-->
  15. <!ATTLIST Query freemarkFormat (false|true) #REQUIRED><!--是否使用FREEMARK标签格式化-->
  16. <!ATTLIST Query resultType CDATA #IMPLIED><!--实体类全名-->
  17. <!ATTLIST Query Alias (true|false) #REQUIRED><!--是否使用了类别名-->

2:建个实体类user.class

  1. package project.master.user;
  2. //import、getting、setting 省略
  3. @Entity
  4. public
    class User extends AbstractEntity {
  5.    private
    static
    final
    long serialVersionUID = 1L;
  6.    @Id
  7.    private String id;
  8.    @Column(unique = true)
  9.    private String phone;// 用户名(手机号)
  10.    private String password;
  11.    private
    int status;// 帐号状态(锁定、停用、正常)
  12.    private Date lastLogin;
  13.    @Column(updatable = false, nullable = false)
  14.    private Date createDate = new Date();
  15. }

3:建立对应的XML (User.query.xml)

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE QueryList SYSTEM "Query.dtd">
  3. <QueryList package="project.master.user.User">
  4.    <Alias name="project.master.user.User" Alias="User" />
  5.    <Alias name="project.freehelp.common.entity.Dictionary" Alias="Dictionary" />
  6.    <Query name="list" type="HQL" freemarkFormat="true" Alias="true">
  7.       <![CDATA[
  8.          FROM User A
  9.          WHERE
  10.          1=1
  11.          <#if id??>
  12.             <#if like??>
  13.                and A.id like '%'||:id||'%'
  14.             <#else>
  15.                and A.id=:id
  16.             </#if>
  17.          </#if>
  18.          <!-- 各字段判断省略 -->
  19.       ]]>
  20.    </Query>
  21.    <Query name="AAX" type="HQL" freemarkFormat="true" Alias="true">
  22.       <!--测试 -->
  23.       SELECT A.phone,(SELECT D.value FROM Dictionary D WHERE D.id='1') as xValue FROM User A
  24.    </Query>
  25.    <Query name="checkUser" type="HQL" freemarkFormat="false" Alias="true">
  26.       SELECT COUNT(1) FROM User A WHERE A.phone=:phone
  27.    </Query>
  28.    <Query name="login" type="HQL" freemarkFormat="false" Alias="true">
  29.        FROM User A WHERE A.phone=:phone and A.password=:password
  30.    </Query>
  31. </QueryList>

4:解析缓存XML

  1. package com.cheuks.bin.db.manager;
  2. //import 省略
  3. public
    class QueryFactory implements QueryType {
  4.  
  5.    private
    final Map<String, Template> FORMAT_XQL = new ConcurrentHashMap<String, Template>();
  6.    private
    final Map<String, String> UNFORMAT_XQL = new ConcurrentHashMap<String, String>();
  7.    private
    final Configuration freemarkerConfiguration = new Configuration(Configuration.VERSION_2_3_0);
  8.    private StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
  9.    private String files;
  10.    public QueryFactory() {
  11.       super();
  12.       freemarkerConfiguration.setTemplateLoader(stringTemplateLoader);
  13.    }
  14.    public
    synchronized
    void put(String name, String XQL, boolean isFormat) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
  15.       if (null == name || null == XQL)
  16.          return;
  17.       if (isFormat) {
  18.          stringTemplateLoader.putTemplate(name, XQL);
  19.          FORMAT_XQL.put(name, freemarkerConfiguration.getTemplate(name));
  20.       } else {
  21.          UNFORMAT_XQL.put(name, XQL);
  22.       }
  23.    }
  24.  
  25.    public String getXQL(String name, boolean isFormat, Map<String, Object> params) throws TemplateException, IOException {
  26.       // if (!isScan)
  27.       // scan();
  28.       if (!isFormat)
  29.          return UNFORMAT_XQL.get(name);
  30.       Template tp = FORMAT_XQL.get(name);
  31.       if (null == tp)
  32.          return
    null;
  33.       StringWriter sw = new StringWriter();
  34.       tp.process(params, sw);
  35.       return sw.toString();
  36.    }
  37.  
  38.    @SuppressWarnings("restriction")
  39.    @javax.annotation.PostConstruct
  40.    private
    void scan() {
  41.       try {
  42.          Set<String> o = null;
  43.          o = Scan.doScan(files);//扫描所有 *.queue.xml
  44.          xmlExplain(o);
  45.       } catch (Exception e) {
  46.          e.printStackTrace();
  47.       }
  48.    }
  49.  
  50.    public String getFiles() {return files;}
  51.    public QueryFactory setFiles(String files) {this.files = files; return
    this;}
  52.  
  53.    public
    void xmlExplain(Set<String> urls) throws ParserConfigurationException, SAXException, IOException {
  54.       Iterator<String> it = urls.iterator();
  55.       SAXParserFactory factory = SAXParserFactory.newInstance();
  56.       SAXParser parser = factory.newSAXParser();
  57.       xmlHandler handler = new xmlHandler();
  58.       XMLReader xmlReader = parser.getXMLReader();
  59.       //读取XML
  60.       xmlReader.setEntityResolver(new EntityResolver() {
  61.          public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
  62.             return
    new InputSource(this.getClass().getClassLoader().getResourceAsStream("dtd/Query.dtd"));
  63.          }
  64.       });
  65.       while (it.hasNext()) {
  66.          String str = it.next();
  67.          InputSource is = new InputSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(str));
  68.          is.setEncoding("utf-8");
  69.          xmlReader.setContentHandler(handler);
  70.          xmlReader.parse(is);
  71.       }
  72.    }
  73.  
  74.    class xmlHandler extends DefaultHandler {
  75.       // private boolean isHQL = false;
  76.       private
    boolean format = false;
  77.       private
    boolean alias = false;
  78.       private String packageName = null;
  79.       private String name = null;
  80.       Map<String, String> aliases = new HashMap<String, String>();
  81.       private String value;
  82.  
  83.       @Override
  84.       public
    void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  85.          if (qName.equals(QUERY_LIST)) {
  86.             packageName = attributes.getValue(PACKAGE);
  87.          } else
    if (qName.equals(QUERY)) {
  88.             // isHQL = attributes.getValue(TYPE).equals("HQL");
  89.             name = attributes.getValue(NAME);
  90.             format = Boolean.valueOf(attributes.getValue(FREEMARK_FORMAT));
  91.             alias = Boolean.valueOf(attributes.getValue(ALIAS));
  92.          } else
    if (qName.equals(ALIAS)) {
  93.             aliases.put(attributes.getValue(ALIAS), attributes.getValue(NAME));
  94.          }
  95.          super.startElement(uri, localName, qName, attributes);
  96.       }
  97.  
  98.       @Override
  99.       public
    void characters(char[] ch, int start, int length) throws SAXException {
  100.          value = new String(ch, start, length).replaceAll("(\n|\t)", "");
  101.          if (value.length() > 0) {
  102.             try {
  103.                put(String.format("%s.%s", packageName, name).toLowerCase(), alias ? alias(value) : value, format);//生成缓存
  104.             } catch (Exception e) {
  105.             }
  106.          }
  107.  
  108.       }
  109.  
  110.       private String alias(String str) {
  111.          if (alias)
  112.             for (Entry<String, String> en : aliases.entrySet())
  113.                str = str.replaceAll(en.getKey(), en.getValue());
  114.          return str;
  115.       }
  116.  
  117.    }
  118. }

 

5:定义 DBAdapter接口。

  1.     public
    interface DBAdapter {
  2.  
  3.    public DBAdapter setSessionFactory(String name);
  4.  
  5.    public <T> List<T> getList(Class<?> c) throws Throwable;
  6.  
  7.    /***
  8.     * query模板查询
  9.     */
  10.    public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, boolean isFormat, Map<String, Object> params) throws Throwable;
  11.  
  12.    /***
  13.     * 模板查询
  14.     */
  15.    public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, Object... params) throws Throwable;
  16.  
  17.    public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, int page, int size, Object... params) throws Throwable;
  18.  
  19.    /***
  20.     * query模板查询 * @param queryName 查询语句名
  21.    public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, boolean isFormat, Map<String, Object> params, int page, int size) throws Throwable;
  22.  
  23.    public String queryNameFormat(Class<?> entry, String queryName);
  24. }

6:写实现(AbstractHibernateDBAdapter、HibernateSingleDBAdapter)

AbstractHibernateDBAdapter

  1. package com.cheuks.bin.db.manager;
  2. @SuppressWarnings({ "rawtypes", "unchecked" })
  3. public
    abstract
    class AbstractHibernateDBAdapter implements DBAdapter {
  4.  
  5.    private QueryFactory queryFactory;
  6.  
  7.    public
    abstract Session getSession();
  8.  
  9.    public <T> List<T> getList(Class<?> c) throws Throwable {
  10.       return getList(c, -1, -1);
  11.    }
  12.  
  13.    public <T> List<T> getList(Class<?> c, int page, int size) throws Throwable {
  14.       Query query = getSession().createQuery(String.format("FROM %s a", c.getSimpleName()));
  15.       List list = page > 0 ? page(query, page, size).list() : query.list();
  16.       return
    null == list ? null : list;
  17.    }
  18.  
  19.    public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, Object... params) throws Throwable {
  20.       return getListByXqlQueryName(queryName, isHQL, -1, -1, params);
  21.    }
  22.  
  23.    public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, int page, int size, Object... params) throws Throwable {
  24.       String xql = queryFactory.getXQL(queryName, false, null);
  25.       Query query = fillParams(isHQL ? getSession().createQuery(xql) : getSession().createSQLQuery(xql), params);
  26.       List list = page > 0 ? page(query, page, size).list() : query.list();
  27.       return
    null == list ? null : list;
  28.    }
  29.  
  30.    public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, boolean isFormat, Map<String, Object> params) throws Throwable {
  31.       return getListByXqlQueryName(queryName, isHQL, isFormat, params, -1, -1);
  32.    }
  33.  
  34.    public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, boolean isFormat, Map<String, Object> params, int page, int size) throws Throwable {
  35.       String xql = queryFactory.getXQL(queryName, isFormat, params);
  36.       Query query = fillParams(isHQL ? getSession().createQuery(xql) : getSession().createSQLQuery(xql), params);
  37.       List list = page > 0 ? page(query, page, size).list() : query.list();
  38.       return
    null == list ? null : list;
  39.    }
  40.  
  41.    protected Query fillParams(Query q, Object... o) {
  42.       if (null == o || null == q) {
  43.          return q;
  44.       }
  45.       for (int i = 0, len = o.length; i < len; i++) {
  46.          q.setParameter(i, o[i]);
  47.       }
  48.       return q;
  49.    }
  50.  
  51.    protected Query fillParams(Query q, Map<String, ?> o) {
  52.       if (null == o || null == q) {
  53.          return q;
  54.       }
  55.       for (Entry<String, ?> en : o.entrySet())
  56.          try {
  57.             q.setParameter(en.getKey(), en.getValue());
  58.          } catch (Exception e) {
  59.          }
  60.       return q;
  61.    }
  62.  
  63.    protected Query page(Query q, int pageNum, int size) {
  64.       if (pageNum >= 0 && size >= 0) {
  65.          q.setFirstResult(size * (pageNum - 1));
  66.          q.setMaxResults(size);
  67.       }
  68.       return q;
  69.    }
  70.  
  71.    public String queryNameFormat(Class<?> entry, String queryName) {
  72.       return String.format("%s.%s", entry.getName(), queryName).toLowerCase();
  73.    }
  74.  
  75.    public QueryFactory getQueryFactory() {
  76.       return queryFactory;
  77.    }
  78.  
  79.    public AbstractHibernateDBAdapter setQueryFactory(QueryFactory queryFactory) {
  80.       this.queryFactory = queryFactory;
  81.       return
    this;
  82.    }
  83. }

 

HibernateSingleDBAdapter

  1. package com.cheuks.bin.db.manager;
  2.  
  3. public
    class HibernateSingleDBAdapter extends AbstractHibernateDBAdapter {
  4.    //待注入 sessionFactory
  5.    private SessionFactory sessionFactory;
  6.    public HibernateSingleDBAdapter setSessionFactory(String name) {
  7.       return
    this;
  8.    }
  9.    @Override
  10.    public Session getSession() {
  11.       return sessionFactory.getCurrentSession();
  12.    }
  13.    public SessionFactory getSessionFactory() {
  14.       return sessionFactory;
  15.    }
  16.    public HibernateSingleDBAdapter setSessionFactory(SessionFactory sessionFactory) {
  17.       this.sessionFactory = sessionFactory;
  18.       return
    this;
  19.    }
  20. }

 

7:注入xml

    <!-- QueryFile 注入 -->

    <bean
id="queryFactory"
class="com.cheuks.bin.db.manager.QueryFactory">

        <property
name="files"
value="*.query.xml"
/>

    </bean>

    <!--Single DBAdapter 注入 -->

    <bean
id="dBAdapter"
class="com.cheuks.bin.db.manager.HibernateSingleDBAdapter">

        <property
name="sessionFactory"
ref="sessionFactory"
/>

        <property
name="queryFactory"
ref="queryFactory"
/>

    </bean>

 

 

8:使用 AbstractDao 、UserDao

AbstractDao

  1. package com.cheuks.bin.db.manager.dao;
  2. public
    abstract
    class AbstractDao<entity, ID extends Serializable> implements BaseDao<entity, ID> {
  3.  
  4.    public
    abstract Class<entity> getEntityClass();
  5.  
  6.    public
    abstract DBAdapter getDBAdapter();
  7.  
  8.    public List<entity> getList(int page, int size) throws Throwable {
  9.       return getDBAdapter().getList(getEntityClass(), page, size);
  10.    }
  11.  
  12.    public List<entity> getList(Map<String, Object> params, int page, int size) throws Throwable {
  13.       return getDBAdapter().getListByXqlQueryName(getDBAdapter().queryNameFormat(getEntityClass(), "list"), true, true, params, page, size);
  14.    }
  15.  
  16.    public <T> List<T> getList(String queryName, Map<String, Object> params, boolean isFromat, int page, int size) throws Throwable {
  17.       return getDBAdapter().getListByXqlQueryName(getDBAdapter().queryNameFormat(getEntityClass(), queryName), true, isFromat, params, page, size);
  18.    }
  19.  
  20.    public <T> List<T> getListCustomQueryName(String queryName, Map<String, Object> params, boolean isFromat, int page, int size) throws Throwable { return getDBAdapter().getListByXqlQueryName(queryName.toLowerCase(), true, isFromat, params, page, size);
  21.    }
  22.  
  23.    public List<entity> getListEntity(String queryName, Map<String, Object> params, boolean isFromat, int page, int size) throws Throwable {
  24.       return getDBAdapter().getListByXqlQueryName(getDBAdapter().queryNameFormat(getEntityClass(), queryName), true, isFromat, params, page, size);
  25.    }
  26.  
  27.    public List<entity> getListEntityCustomQueryName(String queryName, Map<String, Object> params, boolean isFromat, int page, int size) throws Throwable {
  28.       return getDBAdapter().getListByXqlQueryName(queryName.toLowerCase(), true, isFromat, params, page, size);
  29.    }
  30. }

UserDao

  1. package project.freehelp.common.dao.impl;
  2. @Component
  3. public
    class UserInfoDaoImpl extends AbstractDao<UserInfo, String> implements UserInfoDao {
  4.    @Autowired
  5.    private DBAdapter dBAdapter;
  6.    @Override
  7.    public Class<UserInfo> getEntityClass() {
  8.       return UserInfo.class;
  9.    }
  10.    @Override
  11.    public DBAdapter getDBAdapter() {
  12.       return dBAdapter;
  13.    }
  14. }

 

整体就完了。XML部分看DTD。觉得不错可以收藏。但请不要 不名字改了变成自己的成果呀!

Hibernate 拥有 Mybits 的SQL/HQL特性 (注解、XML两不误)的更多相关文章

  1. 【译】Spring 4 + Hibernate 4 + Mysql + Maven集成例子(注解 + XML)

    前言 译文链接:http://websystique.com/spring/spring4-hibernate4-mysql-maven-integration-example-using-annot ...

  2. ABAP 7.52 中的Open SQL新特性

    S/4 HANA 1709 已经在几个月前发布,随之而来的是ABAP 7.52. 本文翻译了更新文档中有关Open SQL的部分 本文链接:http://www.cnblogs.com/hhelibe ...

  3. 灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断

    我们在使用 Hibernate 时一般只会关注是否显示生成的 SQL 语句,不过有些时候还不够.默认时 Hibernate 执行的 SQL 语句是打印在控制台上的,它也可以配置为输出给 Log4J 或 ...

  4. (转)灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断

    背景:项目开发需要.之前对于hibernate日志输出,log4j的绑定,之间的关系一直不是很清楚.终于找到一篇介绍的很详细的文章. 文章出处:https://unmi.cc/hibernate-lo ...

  5. hibernate学习系列-----(4)hibernate基本查询上篇:HQL基本查询

    紧接着上一篇,今天继续hibernate的学习总结,来聊一聊hibernate的基本查询方法,先说说HQL(hibernate Query Language):它是官方推荐的查询语言.在开始写代码之前 ...

  6. 灵活控制 Hibernate 的日志或 SQL 输出(包含参数),以便于诊断

    首先参考:http://blog.csdn.net/zljjava/article/details/7534349  [灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断] 我的具体配置 ...

  7. java数据类型,hibernate数据类型,标准sql数据类型之间的对应表

    Hibernate API简介 其接口分为以下几类: l         提供访问数据库的操作的接口: l         用于配置Hibernate的接口: l         回调接口 l     ...

  8. ABAP 7.40, SP08 中的 Open SQL 新特性

    1,使用 data_source~*指定列 在7.40, SP08中,可以在SELECT语句中使用data_source~*来指定选取不同的数据库表.视图的全部列来作为结果集.它也可以和单独指定的列c ...

  9. atitit.跨语言实现备份mysql数据库 为sql文件特性 api 兼容性java c#.net php js

    atitit.跨语言实现备份mysql数据库 为sql文件特性 api 兼容性java c#.net php js 1. 两个方法:: bat vs mysqldump(推荐)  vs   lang  ...

随机推荐

  1. 【转】c++笔试题

    原文:http://blog.csdn.net/dongfengsun/article/details/1541926 ①链表反转 单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题. ...

  2. [ES6] 19. for ... of

    In ES5, we have for ... in: var phones = ["iPhone", "Nexus", "Nokia"]; ...

  3. MySQL · 特性分析 · MDL 实现分析

    http://mysql.taobao.org/monthly/2015/11/04/ 前言 在MySQL中,DDL是不属于事务范畴的,如果事务和DDL并行执行,操作相关联的表的话,会出现各种意想不到 ...

  4. UNIX基础知识之系统调用与库函数的区别与联系

    上图为UNIX操作系统的体系结构.内核的接口被称为系统调用(system call),公用函数库构建在系统调用接口之上,应用软件既可以使用公用函数库,也可直接使用系统调用. 更详细的说明如下: 所有操 ...

  5. 网口扫盲三:以太网芯片MAC和PHY的关系

    转载:http://www.cnblogs.com/jason-lu/articles/3195473.html   问:如何实现单片以太网微控制器? 答:诀窍是将微控制器.以太网媒体接入控制器(MA ...

  6. java面试笔试谈

    例一: public class Inc { public static void main(String[] args) { Inc inc=new Inc(); int i=5; inc.ferm ...

  7. c++暂停

    #include<cstdlib> 加入这个 然后  system("pause");

  8. selenium python 第一个脚本

    为什么选择python?我的回答很简单,简单易学,功能强大! 下面看看python和selenium 2的结合是什么样子吧 一.第一个selenium python脚本: #coding = utf- ...

  9. linux【报错】userdel: user xiaoming is currently used by process 4713解决

    学习linux的初学者肯定会遇到一些莫名其妙的问题,比如我,在学习删除一个用户的时候,就遇到上面的报错 userdel: user xiaoming is currently used by proc ...

  10. 移动互联网(APP)产品设计的经验分享【转】

    随着移动互联网的发展,越来越多的Web产品开始布局移动端,因此最近经常碰到PM们在交流讨论移动APP产品的设计.我从事移动互联网已经有一年多了,通过不断的学习和实践也积累了一些心得,今天整理并分享一下 ...