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 ...
随机推荐
- Codeforces Round #332 (Div. 2) B. Spongebob and Joke 水题
B. Spongebob and Joke Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/599 ...
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 分块
2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOn ...
- 奇妙华为3c手机, 出现安装未成功问题。
1.我会命令adb uninstall 先卸载我们有签名的安装包. 2.用开发模式在手机上执行我们的应用. 3.然后測试就把手机拿走了,就用应用管理器把我们的应用卸载了. 4.继续装我们的开发包,死活 ...
- Swift 3.0 使用Core Data
swift版本:3.0 Xcode版本:8.0 iOS版本:10.0 自iOS10 和swift3.0 之后,苹果的访问CoreData的方法发生了很大改变,简洁了许多,下面的内容是从0开始建立一个e ...
- android143 360 短信电话拦截
package com.itheima.mobileguard.services; import java.lang.reflect.Method; import android.app.Servic ...
- mysqldump的流程
发布时间:2013 年 4 月 6 日 发布者: OurMySQL 来源:P.Linux Laboratory 前几天看到群里在讨论mysqldump导致锁表的问题,为什么一个表已经dump ...
- pt-online-schema-change原理解析 博客相关需要阅读
xiaoboluo768 http://www.lai18.com/user/481193.html 都说pt-toolkit工具集中的pt-online-schema-change可以在线不锁 ...
- Ruby on Rails Tutorial 第一章 之 搭建开发环境
云端开发环境,Cloud9(https://ide.c9.io/).这个开发环境预先安装好了Rails开发所需要的大多数软件,包括Ruby.RubyGems和Git,需要自己安装Rails. 1.安装 ...
- BootStrap2学习日记12---注册表单
<form method="" action="" class="form-horizontal"> <frameset& ...
- 电商ERP如何接入智选物流平台?
智选物流是综合地址库+时效库+逻辑库(成本.订单属性.仓库)选择出最优快递,通过多家快递网点地址库精准数据,点对点的运输时间,各种行业包裹的所有快递价格逻辑,不同产品类型.支付方式等分析,实现不同仓库 ...