# dexcoder-assistant
**Repository Path**: selfly/dexcoder-assistant
## Basic Information
- **Project Name**: dexcoder-assistant
- **Description**: 已重构发布新版,请移步:https://gitee.com/selfly/sonsure-dumper
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 98
- **Forks**: 59
- **Created**: 2014-12-22
- **Last Updated**: 2023-08-08
## Categories & Tags
**Categories**: database-dev
**Tags**: None
## README
**新版全新重构,更加方便易用,请移步:[https://gitee.com/selfly/sonsure-dumper](https://gitee.com/selfly/sonsure-dumper)**
# Dexcoder快速开发辅助工具包
该通用dal是在开发过程中,对于简单封装的通用dao或数据访问层使用深感痛苦与不便,由此进行了整合和改进发展而来。
如果你不喜欢用`Hibernate`、`Mybaits`这类ORM框架,喜欢`Spring JdbcTemplate`或`DbUtils`,那么可以试试这个封装的通用dal,这可能是目前封装的最方便易用的通用dal层了。
最近更新:
### 版本 2.3.5 更新时间:2016-06-08
- 重构分页功能,支持sql解析方式,用户可自由选择
- 修正Criteria方式先使用queryCount再queryList,order by丢失问题
- 修正RunBinder拦截器事务嵌套有错时,事务回滚出错问题
[详细更新日志](md/update-log.md)
配置动态数据源请看这里:[在dexcoder-dal中使用动态数据源并设置读写分离](md/dy-datasource.md)
数据水平分表请看这里:[在dexcoder-dal中实现分表数据水平拆分](md/multi-table.md)
##核心组件dexcoder-dal使用说明
dexcoder-dal的一些特性:
1. 一个dao即可以搞定所有的实体类,不必再一个个建立跟实体对应的继承于类似BaseDao这类“通用dao”了。
2. 各类方法参数除了`Entity`外,支持更强大的`Criteria`方式。
3. sql的where条件支持一些复杂的条件,如`=`、`!=`、`or`、`in`、`not in`甚至是执行函数。
4. 允许在查询时指定使用哪个字段进行排序,可以指定多个进行组合升降序自由排序。
5. 支持在查询时指定返回字段的白名单和黑名单,可以指定只返回某些字段或不返回某些字段。
6. select查询时支持函数,`count()`、`max()`、`to_char()`、甚至是`distinct`,理论上都可以支持。
7. 方便强大的分页功能,无须额外操作,二三行代码搞定分页,自动判断数据库,无须指定。
8. 可以使用`{}`和`[]`完成一些特殊的操作,`{}`中的代码将原生执行,`[]`中的代码会进行命名转换,一般fieldName转columnName。
9. 支持执行自定义sql。
10. 支持使用类似mybatis的方式执行自定义sql。
11. 支持读写分离和动态数据源。
12. 对于数据分表水平拆分支持友好。
命名上遵循了约定优于配置的原则,典型约定如下:
- 表名约定 `USER_INFO`表实体类名为`UserInfo`。
- 字段名约定 `USER_NAME`实体类中属性名为`userName`。
- 主键名约定 `USER_INFO`表主键名为`USER_INFO_ID`,同理实体类中属性名为`userInfoId`。
- `Oracle`序列名约定 `USER_INFO`表对应的主键序列名为`SEQ_USER_INFO`
当然,这些你可以在扩展中改变它,但不建议这么做,这本身就是一个良好的规范。
要在项目中使用通用dao十分简单,目前已上maven中央库,直接在pom.xml中添加依赖:
com.dexcoder
dexcoder-dal-spring
${version}
然后在spring的配置文件中声明如下bean:
接下来就可以注入到您的`Service`或者其它类中使用了。
##下面是一些常用的方法示例,这里的`Entity`对象为`User`,对于任何的`Entity`都是一样的.
先来看一下`User`对象及它继承的`Pageable`
public class User extends Pageable {
private Long userId;
private String loginName;
private String password;
private Integer userAge;
private String userType;
private String email;
private Date gmtCreate;
//......
}
Pageable对象,用来保存页码、每页条数信息以支持分页
public class Pageable implements Serializable {
/** 每页显示条数 */
protected int itemsPerPage = 20;
/** 当前页码 */
protected int curPage = 1;
//......
}
都是普通的JavaBean对象,下面来看看如何进行具体的增删改查,每种操作都演示了`Entity`和`Criteria`两种方式。
### insert操作
Entity方式
User user = new User();
user.setLoginName("selfly_a");
//......
Long userId = jdbcDao.insert(user);
Criteria 方式
Criteria criteria = Criteria.insert(User.class).into("loginName", "selfly_b").into("password", "12345678")
.into("email", "selflly@foxmail.com").into("userAge", 22).into("userType", "2").into("gmtCreate", new Date());
Long userId = jdbcDao.insert(criteria);
### save操作,和insert的区别在于不处理主键,由调用者指定
Entity方式
User user = new User();
user.setUserId(-1L);
//......
jdbcDao.save(user);
Criteria 方式
Criteria criteria = Criteria.insert(User.class).into("userId", -2L).into("loginName", "selfly-2")
.into("password", "12345678").into("email", "selflly@foxmail.com").into("userAge", 22).into("userType", "2")
.into("gmtCreate", new Date());
jdbcDao.save(criteria);
### update操作
Entity方式
User user = new User();
user.setUserId(57L);
user.setPassword("abcdef");
//方式一 为null的属性值将被忽略
jdbcDao.update(user);
//方式二 为null的属性值将更新到数据库
jdbcDao.update(user,false);
Criteria方式
//criteria方式这里的email设为null也将被更新
Criteria criteria = Criteria.update(User.class).set("password", "update222").set("email",null)
.where("userId", new Object[] { 56L, -1L, -2L });
jdbcDao.update(criteria);
###get操作
根据主键
User user = jdbcDao.get(User.class, 63L);
### Criteria方式
//criteria,主要用来指定字段白名单、黑名单等
Criteria criteria = Criteria.select(User.class).include("loginName");
User user = jdbcDao.get(criteria, 73L);
###delete操作
根据主键
jdbcDao.delete(User.class, 57L);
Entity方式
//会把不为空的属性做为where条件
User u = new User();
u.setLoginName("selfly-1");
u.setUserType("1");
jdbcDao.delete(u);
Criteria方式
//where条件使用了or
Criteria criteria = Criteria.delete(User.class).where("loginName", new Object[] { "liyd2" })
.or("userAge", new Object[]{64});
jdbcDao.delete(criteria);
### 列表查询操作
所有结果
List users = jdbcDao.queryList(User.class);
以Entity中不为空的属性作为查询条件
User user = new User();
user.setUserType("1");
//......
List users = jdbcDao.queryList(user);
Criteria方式,可以指定黑白名单、排序字段等
Criteria criteria = Criteria.select(User.class).exclude("userId")
.where("loginName", new Object[]{"liyd"}).asc("userAge").desc("userId");
List users = jdbcDao.queryList(criteria);
指定逻辑操作符
//使用了like,可以换成!=、in、not in等
Criteria criteria = Criteria.select(User.class).where("loginName", "like",
new Object[] { "%liyd%" });
user.setUserAge(16);
//这里entity跟criteria方式混合使用了,建议少用
List users = jdbcDao.queryList(user, criteria.include("userId"));
### count记录数查询,除了返回值不一样外,其它和列表查询一致
//Entity方式
user.setUserName("liyd");
int count = jdbcDao.queryCount(user);
//Criteria方式
Criteria criteria = Criteria.select(User.class).where("loginName", new Object[] { "liyd" })
.or("userAge", new Object[]{27});
int count = jdbcDao.queryCount(criteria);
### 查询单个结果,参数使用方式同上
//Entity
User user = jdbcDao.querySingleResult(user);
//Criteria
Criteria criteria = Criteria.select(User.class).where("loginName", new Object[] { "liyd" })
.and("userId", new Object[]{23L});
User u = jdbcDao.querySingleResult(criteria);
### 指定属性白名单,在任何查询方法中都可以使用
//将只返回loginName
Criteria criteria = Criteria.select(User.class).include("loginName");
User u = jdbcDao.get(criteria, 23L);
### 指定属性黑名单,在任何查询方法中都可以使用
//将不返回loginName
Criteria criteria = Criteria.select(User.class).exclude("loginName");
User u = jdbcDao.get(criteria, 23L);
### 指定排序
//指定多个排序字段,asc、desc
Criteria criteria = Criteria.select(User.class).exclude("userId")
.where("loginName", new Object[]{"liyd"}).asc("userId").desc("userAge");
List users = jdbcDao.queryList(criteria);
### 分页
直接传入Entity,继承于`Pageable`
//进行分页,只需要增加这行,列表查询方式跟上面没有任何区别
PageControl.performPage(user);
//分页后该方法即返回null,由PageControl中获取
jdbcDao.queryList(user);
Pager pager = PageControl.getPager();
//列表
List users = pager.getList(User.class);
//总记录数
int itemsTotal = pager.getItemsTotal();
直接传入页码和每页大小
//直接传入页码和每页条数
PageControl.performPage(1, 10);
//使用Criteria方式,并指定排序字段方式为asc
Criteria criteria = Criteria.select(User.class).include("loginName", "userId")
.where("loginName", new Object[]{"liyd"}).asc("userId");
jdbcDao.queryList(criteria);
Pager pager = PageControl.getPager();
### 使用智能分页解析
默认使用的简单分页在数据量较大,在自动做`count()`查询时可能会出现效率问题.
这时可以选用sql解析的智能分页.
只需要在声明`PageControl`时注入`SmartPageSqlHandler`来替换默认的`SimplePageSqlHandler`即可:
同时别忘了,使用智能分页需要添加`JSqlParser`的依赖:
com.github.jsqlparser
jsqlparser
${jsqlparser.version}
### 不同的属性在括号内or的情况:
Criteria criteria = Criteria.select(User.class)
.where("userType", new Object[] { "1" }).begin()
.and("loginName", new Object[] { "selfly" })
.or("email", new Object[] { "javaer@live.com" }).end()
.and("password", new Object[] { "123456" });
User user = jdbcDao.querySingleResult(criteria);
### 执行函数
//max()
Criteria criteria = Criteria.select(User.class).addSelectFunc("max([userId])");
Long userId = jdbcDao.queryForObject(criteria);
//count()
Criteria criteria = Criteria.select(User.class).addSelectFunc("count(*)");
Long count = jdbcDao.queryForObject(criteria);
//distinct
Criteria criteria = Criteria.select(User.class).addSelectFunc("distinct [loginName]");
List