在Web开发中,一般都分3层。
Controller/Action 控制层,
Service/Business 服务层/业务逻辑层,
Dao 数据访问层/数据持久层。

在学习和工作的实践过程中,我发现很多功能是比较通用的,我们可以把他们抽象成API接口。

下文通过一段较长的代码,Hibernate实现,来展示如何设计一些通用的API。

说明:代码只是起到一个示范(Demo)的作用,实际上完全可以做得更强大。
我最近已经在现在的基础上大大改进了,现在把比较基础的实现分享给大家。

package cn.fansunion.demo.db.dao; 

import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import javax.annotation.Resource; import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory; import cn.fansunion.common.util.EmptyUtils; /**
* Dao的父类。采用泛型,实现了 一些通用的功能,大大减少了子类代码的重复。 * 目前只能适用于1个表或实体。
*
* @author leiwen@fansunion.cn
*/
public abstract class BaseDao<T> { private Class<T> modelClazz; @Resource
private SessionFactory sessionFactory; // ////////////////////////////////////////////////////////////// public BaseDao() {
this.modelClazz = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
} // //////////////////////////////////////////////////////
// //////////////////////泛型方法-CRUD/////////////////////////
// ///////////////////////////////////////////////////// /**
* 根据主键查询
*
* @param id
* 主键
* @return 实体对象
*/
public T get(Integer id) {
T entity = (T) getCurrentSession().get(modelClazz, id);
return entity;
} /**
* 增加
*
* @param entity
* 实体对象
*/
public void add(T entity) {
getCurrentSession().save(entity); } /**
* 物理删除
*
* @param entity
* 实体对象
*/
public void delete(T entity) {
getCurrentSession().delete(entity);
} /**
* 更新
*
* @param entity
* 持久态的实体对象
*/
public void update(T entity) {
getCurrentSession().update(entity);
} /**
* 逻辑删除
*
* @param id
* 主键
*/
public void remove(Integer id) { Session session = getCurrentSession();
String sql = "update " + modelClazz
+ " set isDeleted = 1 where id = :id";
Query query = session.createQuery(sql);
query.setParameter("id", id);
query.executeUpdate(); } // ///////////////////////////////////////////////
// ////////////获取记录总数/////////////////////////
// ///////////////////////////////////////////////
/**
* 获得1个整数
*
* @param hql
* hql语句
* @return 1个整数
*/
protected Integer getCount(String hql) {
Integer count = 0;
Query query = createQuery(hql);
count = getCount(query);
return count;
} protected Integer getCount(String hql, String key, Object value) {
Integer count = 0;
Query query = createQuery(hql, key, value);
count = getCount(query);
return count;
} // 带参数的hql语句
protected Integer getCount(String hql, Map<String, Object> params) {
Integer count = 0;
Query query = createQuery(hql, params);
count = getCount(query);
return count;
} private Integer getCount(Query query) {
Integer count = 0;
Object uniqueResult = query.uniqueResult();
if (uniqueResult != null) {
count = Integer.parseInt(uniqueResult.toString());
}
return count;
} // ///////////////////////////////////////////////
// ////////////获取一个对象/////////////////////////
// ///////////////////////////////////////////////
protected List findByProperty(String name, Object value) {
String hql = "from " + modelClazz.getSimpleName() + " where " + name
+ "=" + ":" + name;
return executeQueryList(hql, name, value);
} protected T executeQueryUnique(String hql) {
T result = null;
List<T> list = executeQueryList(hql);
if (list != null && list.size() >= 1) {
result = list.get(0);
}
return result;
} protected T executeQueryUnique(String hql, String key, Object value) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(key, value);
return executeQueryUnique(hql, params);
} // 根据属性获得对象
protected T executeQueryUnique(String hql, String key1, Object value1,
String key2, Object value2) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(key1, value1);
params.put(key2, value2);
return executeQueryUnique(hql, params);
} protected T executeQueryUnique(String hql, Map<String, Object> params) {
T result = null;
List<T> list = executeQueryList(hql, params);
if (EmptyUtils.isNotEmpty(list)) {
result = list.get(0);
}
return result;
} // ///////////////////////////////////////////////
// //////////////获取一个列表(不使用泛型 List<T>)/////////////////
// ///////////////////////////////////////////////
// 执行不带参数的hql查询,返回一个结果集List
protected List executeQueryList(String hql) {
return executeQueryList(hql, null);
} protected List executeQueryList(String hql, String key, Object value) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(key, value);
return executeQueryList(hql, params);
} protected List executeQueryList(String hql, String key1, Object value1,
String key2, Object value2) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(key1, value1);
params.put(key2, value2);
return executeQueryList(hql, params);
} protected List executeQueryList(String hql, Map<String, Object> params) {
return executeQueryList(hql, params, -1, -1);
} protected List executeQueryList(String hql, Integer firstResult,
Integer maxResults) {
return executeQueryList(hql, null, firstResult, maxResults);
} protected List executeQueryList(String hql, String key, Object value,
Integer firstResult, Integer maxResults) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(key, value);
return executeQueryList(hql, params, firstResult, maxResults);
} // 执行带参数并且含有分页的hql查询
protected List executeQueryList(String hql, Map<String, Object> params,
Integer firstResult, Integer maxResults) {
Query query = createQuery(hql, params);
if (firstResult > 0) {
query.setFirstResult(firstResult);
} if (maxResults > 0) {
query.setMaxResults(maxResults);
} return query.list();
} // ///////////////////////////////////////////////
// ////////////更新操作/////////////////////////
// /////////////////////////////////////////////// protected int executeUpdate(String hql) {
return executeUpdate(hql, null);
} protected int executeUpdate(String hql, String key, Object value) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(key, value);
return executeUpdate(hql, params);
} protected int executeUpdate(String hql, String key1, Object value1,
String key2, Object value2) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(key1, value1);
params.put(key2, value2);
return executeUpdate(hql, params);
} // 执行带参数的hql更新语句
protected int executeUpdate(String hql, Map<String, Object> params) {
Query query = createQuery(hql, params);
return query.executeUpdate();
} // ///////////////////////////////////////////////
// ////////////创建Query对象/////////////////////////
// ///////////////////////////////////////////////
private Query createQuery(String hql, Map<String, Object> params) {
Query query = getCurrentSession().createQuery(hql);
if (params != null) {
Set<Entry<String, Object>> entrySet = params.entrySet();
for (Map.Entry<String, Object> entry : entrySet) {
Object value = entry.getValue();
String key = entry.getKey();
if (value instanceof Collection) {
query.setParameterList(key, (Collection) value);
} else if (value instanceof Object[]) {
query.setParameterList(key, (Object[]) value);
} else {
query.setParameter(key, value);
}
}
}
return query;
} private Query createQuery(String hql, String key, Object value) {
Query query = getCurrentSession().createQuery(hql);
if (key != null) {
query.setParameter(key, value);
}
return query;
} private Query createQuery(String hql) {
return getCurrentSession().createQuery(hql);
} /**
* 获取主数源
*/
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
} }

在工作和学习的实践中,我发现Web开发有很大程度上的通用性。

我希望,也在努力地总结这些规律,争取早点弄出一套可以大大提高生产力的方法和代码框架。

技术不能改变程序员的命运,而生产力可以。

提高生产力,是我目前迫切的追求。

过去,现在和未来,我都将为之而努力。

我的博客网站:http://FansUnion.cn

原文参见:http://fansunion.cn/articles/2264

数据持久层(DAO)通用API的实现的更多相关文章

  1. [置顶] 数据持久层(DAO)常用功能–通用API的实现

    在Web开发中,一般都分3层. Controller/Action 控制层, Service/Business 服务层/业务逻辑层, Dao 数据访问层/数据持久层. 在学习和工作的实践过程中,我发现 ...

  2. Java数据持久层

    一.前言 1.持久层 Java数据持久层,其本身是为了实现与数据源进行数据交互的存在,其目的是通过分层架构风格,进行应用&数据的解耦. 我从整体角度,依次阐述JDBC.Mybatis.Myba ...

  3. Restful.Data v1.0 - 轻量级数据持久层组件, 正式开源发布了

    经过几个星期的优化调整,今天 Restful.Data 正式开源发布. 源码地址:https://github.com/linli8/Restful 今天不写那么多废话了,还是重新介绍一下 Restf ...

  4. Java数据持久层框架 MyBatis之背景知识一

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

  5. .NET平台下,关于数据持久层框架

    在.NET平台下,关于数据持久层框架非常多,本文主要对如下几种做简要的介绍并推荐一些学习的资源: 1.NHibernate 2.NBear 3.Castle ActiveRecord 4.iBATIS ...

  6. .NET开源项目介绍及资源推荐:数据持久层

    在.NET平台下,关于数据持久层框架非常多,本文主要对如下几种做简要的介绍并推荐一些学习的资源: 1.NHibernate 2.NBear 3.Castle ActiveRecord 4.iBATIS ...

  7. c++ 数据持久层研究(一)

    C++ORM框架自动生成代码数据库  用过Java的都知道SSH框架,特别对于数据库开发,Java领域有无数的ORM框架,供数据持久层调用,如Hibernate,iBatis(现在改名叫MyBatis ...

  8. UWP开发之ORM实践:如何使用Entity Framework Core做SQLite数据持久层?

    选择SQLite的理由 在做UWP开发的时候我们首选的本地数据库一般都是Sqlite,我以前也不知道为啥?后来仔细研究了一下也是有原因的: 1,微软做的UWP应用大部分也是用Sqlite.或者说是微软 ...

  9. .NET平台数据持久层框架

    在.NET平台下的几个数据持久层框架: 1.NHibernate 2.NBear 3.Castle ActiveRecord 4.iBATIS.NET 5.DAAB 6.DLinq

随机推荐

  1. 泛型和面向对象C++

    1. 在类内部定义的函数默觉得inline,内联函数应该在头文件里定义,由于其定义对编译器必须是可见的,以便编译器可以在调用点内联展开该函数的代码. 此时,仅有函数原型是不够的. 2.assert 3 ...

  2. 试试pypy

    pypy是一个python的解释器和JIT编译器.能够在不改动不论什么代码的情况下大幅提升python代码的性能. 使用超级简单,在官网下载编译好的二进制包进行安装,然后然后执行代码的时候指定这个解释 ...

  3. PCB WCF Web接口增减参数后,在客户端不更新的情况,是否影响客户端,评估测试

    1.目的:由于接口众多,服务端变更接口,会造成服务停用更新,造成客户端不能使用或报错, 在此评估[Web中心]此服务端,接口接口参数增加或减少,是否对客户端造成影响 2.评估内容:服务端增加单值参数, ...

  4. Promise-js异步加载解决方案

    范例: var p = new Promise(function(resolve, reject){ //做一些异步操作 setTimeout(function(){ console.log('执行完 ...

  5. OneThink管理平台 ,登录后台一直提示验证码错误

    可能是数据库的错.上传到服务器以后要改2个地方的配置,\Application\Common\Conf\config.php(整站公用配置文 件),\Application\User\Conf\con ...

  6. Spring Boot (13) druid监控

    druid druid是和tomcat jdbc一样优秀的连接池,出自阿里巴巴.除了连接池,druid哈hi有一个很实用的监控功能. pom.xml 添加了以下依赖后,会自动用druid连接池替代默认 ...

  7. MVC微信浏览器图片上传(img转Base64)

    因公司业务需要,需要做一个微信公众号里的图片上传功能,主要用到的技术就是 img转base64 上到服务器 话不多说, 贴代码 先看前端显示出来的东西 OK 图片不重要,看代码 <!--微信图片 ...

  8. 网上干货 ElasticSearch详解与优化设计

    https://blog.csdn.net/joez/article/details/52171199?locationNum=3&fps=1 分析得很好,需要仔细阅读 问题遗留点: Fiel ...

  9. 前端-Vue学习思维导图笔记

    看不清的朋友右键保存或者新窗口打开哦!喜欢我可以关注我,还有更多前端思维导图笔记有vue结构分析,JS基础,JQ,JS高级,Angular,git等等

  10. android黑科技系列——Wireshark和Fiddler分析Android中的TLS协议包数据(附带案例样本)

    一.前言 在之前一篇文章已经介绍了一款网络访问软件的破解教程,当时采用的突破口是应用程序本身的一个漏洞,就是没有关闭日志信息,我们通过抓取日志获取到关键信息来找到突破口进行破解的.那篇文章也说到了,如 ...