Hibernate 拥有 Mybits 的SQL/HQL特性 (注解、XML两不误)
第一次写博客。文章有点渣,喜欢就看看,不喜欢路过点个赞。
效果:直接一条语句多种用法
- FROM User A
- WHERE
- 1=1
- <#if id??>
- <#if like??>
- and A.id like '%'||:id||'%'
- <#else>
- and A.id=:id
- </#if>
- </#if>
先来原理 HQL/SQL + Freemarker 模版生成查询语句。
1:把SQL/HQL写在XML。
2:编写文件扫描器(缺)
3:读取解释XML
4:按实体类空间缓存查询语句
5:直接使用
注意:不要直接复制,先弄懂流程,因为这源于旧版本及测试包来写的,也省略了部分代码,因此包路径有问题。程序也不完整,缺了的自己让大家自己去思考实现。基本上依赖Spring,不依赖Spring注入的可以考虑用代理模式注入(反射/生成字节码(javassist/asm)/CGLIB等)
1:为了方便先定义约束Query.dtd
- <?xml version="1.0" encoding="UTF-8"?>
- <!ELEMENT QueryList (Alias*,Query*)>
- <!--<!ELEMENT Context (CachePool,Bean*,Intercept*,ScanToPack*,CloneModel)>-->
- <!ELEMENT Alias EMPTY><!--别名-->
- <!ELEMENT Query (#PCDATA)><!--sql/hql-->
- <!--QueryList-->
- <!ATTLIST QueryList package CDATA #REQUIRED>
- <!--Alias-->
- <!ATTLIST Alias name CDATA #REQUIRED><!--实体类全名-->
- <!ATTLIST Alias Alias CDATA #REQUIRED><!--SQL/HQL 语句中的实体类别名-->
- <!--Query-->
- <!ATTLIST Query name CDATA #REQUIRED><!--实体类全名-->
- <!ATTLIST Query type (HQL|SQL) #REQUIRED><!--语句类型:HQL/SQL-->
- <!ATTLIST Query freemarkFormat (false|true) #REQUIRED><!--是否使用FREEMARK标签格式化-->
- <!ATTLIST Query resultType CDATA #IMPLIED><!--实体类全名-->
- <!ATTLIST Query Alias (true|false) #REQUIRED><!--是否使用了类别名-->
2:建个实体类user.class
- package project.master.user;
- //import、getting、setting 省略
- @Entity
- public
class User extends AbstractEntity { - private
static
final
long serialVersionUID = 1L; - @Id
- private String id;
- @Column(unique = true)
- private String phone;// 用户名(手机号)
- private String password;
- private
int status;// 帐号状态(锁定、停用、正常) - private Date lastLogin;
- @Column(updatable = false, nullable = false)
- private Date createDate = new Date();
- }
3:建立对应的XML (User.query.xml)
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE QueryList SYSTEM "Query.dtd">
- <QueryList package="project.master.user.User">
- <Alias name="project.master.user.User" Alias="User" />
- <Alias name="project.freehelp.common.entity.Dictionary" Alias="Dictionary" />
- <Query name="list" type="HQL" freemarkFormat="true" Alias="true">
- <![CDATA[
- FROM User A
- WHERE
- 1=1
- <#if id??>
- <#if like??>
- and A.id like '%'||:id||'%'
- <#else>
- and A.id=:id
- </#if>
- </#if>
- <!-- 各字段判断省略 -->
- ]]>
- </Query>
- <Query name="AAX" type="HQL" freemarkFormat="true" Alias="true">
- <!--测试 -->
- SELECT A.phone,(SELECT D.value FROM Dictionary D WHERE D.id='1') as xValue FROM User A
- </Query>
- <Query name="checkUser" type="HQL" freemarkFormat="false" Alias="true">
- SELECT COUNT(1) FROM User A WHERE A.phone=:phone
- </Query>
- <Query name="login" type="HQL" freemarkFormat="false" Alias="true">
- FROM User A WHERE A.phone=:phone and A.password=:password
- </Query>
- </QueryList>
4:解析缓存XML
- package com.cheuks.bin.db.manager;
- //import 省略
- public
class QueryFactory implements QueryType { - private
final Map<String, Template> FORMAT_XQL = new ConcurrentHashMap<String, Template>(); - private
final Map<String, String> UNFORMAT_XQL = new ConcurrentHashMap<String, String>(); - private
final Configuration freemarkerConfiguration = new Configuration(Configuration.VERSION_2_3_0); - private StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
- private String files;
- public QueryFactory() {
- super();
- freemarkerConfiguration.setTemplateLoader(stringTemplateLoader);
- }
- public
synchronized
void put(String name, String XQL, boolean isFormat) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException { - if (null == name || null == XQL)
- return;
- if (isFormat) {
- stringTemplateLoader.putTemplate(name, XQL);
- FORMAT_XQL.put(name, freemarkerConfiguration.getTemplate(name));
- } else {
- UNFORMAT_XQL.put(name, XQL);
- }
- }
- public String getXQL(String name, boolean isFormat, Map<String, Object> params) throws TemplateException, IOException {
- // if (!isScan)
- // scan();
- if (!isFormat)
- return UNFORMAT_XQL.get(name);
- Template tp = FORMAT_XQL.get(name);
- if (null == tp)
- return
null; - StringWriter sw = new StringWriter();
- tp.process(params, sw);
- return sw.toString();
- }
- @SuppressWarnings("restriction")
- @javax.annotation.PostConstruct
- private
void scan() { - try {
- Set<String> o = null;
- o = Scan.doScan(files);//扫描所有 *.queue.xml
- xmlExplain(o);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public String getFiles() {return files;}
- public QueryFactory setFiles(String files) {this.files = files; return
this;} - public
void xmlExplain(Set<String> urls) throws ParserConfigurationException, SAXException, IOException { - Iterator<String> it = urls.iterator();
- SAXParserFactory factory = SAXParserFactory.newInstance();
- SAXParser parser = factory.newSAXParser();
- xmlHandler handler = new xmlHandler();
- XMLReader xmlReader = parser.getXMLReader();
- //读取XML
- xmlReader.setEntityResolver(new EntityResolver() {
- public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
- return
new InputSource(this.getClass().getClassLoader().getResourceAsStream("dtd/Query.dtd")); - }
- });
- while (it.hasNext()) {
- String str = it.next();
- InputSource is = new InputSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(str));
- is.setEncoding("utf-8");
- xmlReader.setContentHandler(handler);
- xmlReader.parse(is);
- }
- }
- class xmlHandler extends DefaultHandler {
- // private boolean isHQL = false;
- private
boolean format = false; - private
boolean alias = false; - private String packageName = null;
- private String name = null;
- Map<String, String> aliases = new HashMap<String, String>();
- private String value;
- @Override
- public
void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - if (qName.equals(QUERY_LIST)) {
- packageName = attributes.getValue(PACKAGE);
- } else
if (qName.equals(QUERY)) { - // isHQL = attributes.getValue(TYPE).equals("HQL");
- name = attributes.getValue(NAME);
- format = Boolean.valueOf(attributes.getValue(FREEMARK_FORMAT));
- alias = Boolean.valueOf(attributes.getValue(ALIAS));
- } else
if (qName.equals(ALIAS)) { - aliases.put(attributes.getValue(ALIAS), attributes.getValue(NAME));
- }
- super.startElement(uri, localName, qName, attributes);
- }
- @Override
- public
void characters(char[] ch, int start, int length) throws SAXException { - value = new String(ch, start, length).replaceAll("(\n|\t)", "");
- if (value.length() > 0) {
- try {
- put(String.format("%s.%s", packageName, name).toLowerCase(), alias ? alias(value) : value, format);//生成缓存
- } catch (Exception e) {
- }
- }
- }
- private String alias(String str) {
- if (alias)
- for (Entry<String, String> en : aliases.entrySet())
- str = str.replaceAll(en.getKey(), en.getValue());
- return str;
- }
- }
- }
5:定义 DBAdapter接口。
- public
interface DBAdapter { - public DBAdapter setSessionFactory(String name);
- public <T> List<T> getList(Class<?> c) throws Throwable;
- /***
- * query模板查询
- */
- public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, boolean isFormat, Map<String, Object> params) throws Throwable;
- /***
- * 模板查询
- */
- public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, Object... params) throws Throwable;
- public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, int page, int size, Object... params) throws Throwable;
- /***
- * query模板查询 * @param queryName 查询语句名
- public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, boolean isFormat, Map<String, Object> params, int page, int size) throws Throwable;
- public String queryNameFormat(Class<?> entry, String queryName);
- }
6:写实现(AbstractHibernateDBAdapter、HibernateSingleDBAdapter)
AbstractHibernateDBAdapter
- package com.cheuks.bin.db.manager;
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public
abstract
class AbstractHibernateDBAdapter implements DBAdapter { - private QueryFactory queryFactory;
- public
abstract Session getSession(); - public <T> List<T> getList(Class<?> c) throws Throwable {
- return getList(c, -1, -1);
- }
- public <T> List<T> getList(Class<?> c, int page, int size) throws Throwable {
- Query query = getSession().createQuery(String.format("FROM %s a", c.getSimpleName()));
- List list = page > 0 ? page(query, page, size).list() : query.list();
- return
null == list ? null : list; - }
- public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, Object... params) throws Throwable {
- return getListByXqlQueryName(queryName, isHQL, -1, -1, params);
- }
- public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, int page, int size, Object... params) throws Throwable {
- String xql = queryFactory.getXQL(queryName, false, null);
- Query query = fillParams(isHQL ? getSession().createQuery(xql) : getSession().createSQLQuery(xql), params);
- List list = page > 0 ? page(query, page, size).list() : query.list();
- return
null == list ? null : list; - }
- public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, boolean isFormat, Map<String, Object> params) throws Throwable {
- return getListByXqlQueryName(queryName, isHQL, isFormat, params, -1, -1);
- }
- public <T> List<T> getListByXqlQueryName(String queryName, boolean isHQL, boolean isFormat, Map<String, Object> params, int page, int size) throws Throwable {
- String xql = queryFactory.getXQL(queryName, isFormat, params);
- Query query = fillParams(isHQL ? getSession().createQuery(xql) : getSession().createSQLQuery(xql), params);
- List list = page > 0 ? page(query, page, size).list() : query.list();
- return
null == list ? null : list; - }
- protected Query fillParams(Query q, Object... o) {
- if (null == o || null == q) {
- return q;
- }
- for (int i = 0, len = o.length; i < len; i++) {
- q.setParameter(i, o[i]);
- }
- return q;
- }
- protected Query fillParams(Query q, Map<String, ?> o) {
- if (null == o || null == q) {
- return q;
- }
- for (Entry<String, ?> en : o.entrySet())
- try {
- q.setParameter(en.getKey(), en.getValue());
- } catch (Exception e) {
- }
- return q;
- }
- protected Query page(Query q, int pageNum, int size) {
- if (pageNum >= 0 && size >= 0) {
- q.setFirstResult(size * (pageNum - 1));
- q.setMaxResults(size);
- }
- return q;
- }
- public String queryNameFormat(Class<?> entry, String queryName) {
- return String.format("%s.%s", entry.getName(), queryName).toLowerCase();
- }
- public QueryFactory getQueryFactory() {
- return queryFactory;
- }
- public AbstractHibernateDBAdapter setQueryFactory(QueryFactory queryFactory) {
- this.queryFactory = queryFactory;
- return
this; - }
- }
HibernateSingleDBAdapter
- package com.cheuks.bin.db.manager;
- public
class HibernateSingleDBAdapter extends AbstractHibernateDBAdapter { - //待注入 sessionFactory
- private SessionFactory sessionFactory;
- public HibernateSingleDBAdapter setSessionFactory(String name) {
- return
this; - }
- @Override
- public Session getSession() {
- return sessionFactory.getCurrentSession();
- }
- public SessionFactory getSessionFactory() {
- return sessionFactory;
- }
- public HibernateSingleDBAdapter setSessionFactory(SessionFactory sessionFactory) {
- this.sessionFactory = sessionFactory;
- return
this; - }
- }
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
- package com.cheuks.bin.db.manager.dao;
- public
abstract
class AbstractDao<entity, ID extends Serializable> implements BaseDao<entity, ID> { - public
abstract Class<entity> getEntityClass(); - public
abstract DBAdapter getDBAdapter(); - public List<entity> getList(int page, int size) throws Throwable {
- return getDBAdapter().getList(getEntityClass(), page, size);
- }
- public List<entity> getList(Map<String, Object> params, int page, int size) throws Throwable {
- return getDBAdapter().getListByXqlQueryName(getDBAdapter().queryNameFormat(getEntityClass(), "list"), true, true, params, page, size);
- }
- public <T> List<T> getList(String queryName, Map<String, Object> params, boolean isFromat, int page, int size) throws Throwable {
- return getDBAdapter().getListByXqlQueryName(getDBAdapter().queryNameFormat(getEntityClass(), queryName), true, isFromat, params, page, size);
- }
- 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);
- }
- public List<entity> getListEntity(String queryName, Map<String, Object> params, boolean isFromat, int page, int size) throws Throwable {
- return getDBAdapter().getListByXqlQueryName(getDBAdapter().queryNameFormat(getEntityClass(), queryName), true, isFromat, params, page, size);
- }
- public List<entity> getListEntityCustomQueryName(String queryName, Map<String, Object> params, boolean isFromat, int page, int size) throws Throwable {
- return getDBAdapter().getListByXqlQueryName(queryName.toLowerCase(), true, isFromat, params, page, size);
- }
- }
UserDao
- package project.freehelp.common.dao.impl;
- @Component
- public
class UserInfoDaoImpl extends AbstractDao<UserInfo, String> implements UserInfoDao { - @Autowired
- private DBAdapter dBAdapter;
- @Override
- public Class<UserInfo> getEntityClass() {
- return UserInfo.class;
- }
- @Override
- public DBAdapter getDBAdapter() {
- return dBAdapter;
- }
- }
整体就完了。XML部分看DTD。觉得不错可以收藏。但请不要 不名字改了变成自己的成果呀!
Hibernate 拥有 Mybits 的SQL/HQL特性 (注解、XML两不误)的更多相关文章
- 【译】Spring 4 + Hibernate 4 + Mysql + Maven集成例子(注解 + XML)
前言 译文链接:http://websystique.com/spring/spring4-hibernate4-mysql-maven-integration-example-using-annot ...
- ABAP 7.52 中的Open SQL新特性
S/4 HANA 1709 已经在几个月前发布,随之而来的是ABAP 7.52. 本文翻译了更新文档中有关Open SQL的部分 本文链接:http://www.cnblogs.com/hhelibe ...
- 灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断
我们在使用 Hibernate 时一般只会关注是否显示生成的 SQL 语句,不过有些时候还不够.默认时 Hibernate 执行的 SQL 语句是打印在控制台上的,它也可以配置为输出给 Log4J 或 ...
- (转)灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断
背景:项目开发需要.之前对于hibernate日志输出,log4j的绑定,之间的关系一直不是很清楚.终于找到一篇介绍的很详细的文章. 文章出处:https://unmi.cc/hibernate-lo ...
- hibernate学习系列-----(4)hibernate基本查询上篇:HQL基本查询
紧接着上一篇,今天继续hibernate的学习总结,来聊一聊hibernate的基本查询方法,先说说HQL(hibernate Query Language):它是官方推荐的查询语言.在开始写代码之前 ...
- 灵活控制 Hibernate 的日志或 SQL 输出(包含参数),以便于诊断
首先参考:http://blog.csdn.net/zljjava/article/details/7534349 [灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断] 我的具体配置 ...
- java数据类型,hibernate数据类型,标准sql数据类型之间的对应表
Hibernate API简介 其接口分为以下几类: l 提供访问数据库的操作的接口: l 用于配置Hibernate的接口: l 回调接口 l ...
- ABAP 7.40, SP08 中的 Open SQL 新特性
1,使用 data_source~*指定列 在7.40, SP08中,可以在SELECT语句中使用data_source~*来指定选取不同的数据库表.视图的全部列来作为结果集.它也可以和单独指定的列c ...
- atitit.跨语言实现备份mysql数据库 为sql文件特性 api 兼容性java c#.net php js
atitit.跨语言实现备份mysql数据库 为sql文件特性 api 兼容性java c#.net php js 1. 两个方法:: bat vs mysqldump(推荐) vs lang ...
随机推荐
- 【转】c++笔试题
原文:http://blog.csdn.net/dongfengsun/article/details/1541926 ①链表反转 单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题. ...
- [ES6] 19. for ... of
In ES5, we have for ... in: var phones = ["iPhone", "Nexus", "Nokia"]; ...
- MySQL · 特性分析 · MDL 实现分析
http://mysql.taobao.org/monthly/2015/11/04/ 前言 在MySQL中,DDL是不属于事务范畴的,如果事务和DDL并行执行,操作相关联的表的话,会出现各种意想不到 ...
- UNIX基础知识之系统调用与库函数的区别与联系
上图为UNIX操作系统的体系结构.内核的接口被称为系统调用(system call),公用函数库构建在系统调用接口之上,应用软件既可以使用公用函数库,也可直接使用系统调用. 更详细的说明如下: 所有操 ...
- 网口扫盲三:以太网芯片MAC和PHY的关系
转载:http://www.cnblogs.com/jason-lu/articles/3195473.html 问:如何实现单片以太网微控制器? 答:诀窍是将微控制器.以太网媒体接入控制器(MA ...
- java面试笔试谈
例一: public class Inc { public static void main(String[] args) { Inc inc=new Inc(); int i=5; inc.ferm ...
- c++暂停
#include<cstdlib> 加入这个 然后 system("pause");
- selenium python 第一个脚本
为什么选择python?我的回答很简单,简单易学,功能强大! 下面看看python和selenium 2的结合是什么样子吧 一.第一个selenium python脚本: #coding = utf- ...
- linux【报错】userdel: user xiaoming is currently used by process 4713解决
学习linux的初学者肯定会遇到一些莫名其妙的问题,比如我,在学习删除一个用户的时候,就遇到上面的报错 userdel: user xiaoming is currently used by proc ...
- 移动互联网(APP)产品设计的经验分享【转】
随着移动互联网的发展,越来越多的Web产品开始布局移动端,因此最近经常碰到PM们在交流讨论移动APP产品的设计.我从事移动互联网已经有一年多了,通过不断的学习和实践也积累了一些心得,今天整理并分享一下 ...