初识和创建SmartDb
简介SmartDb理念和思想,以及对SmartDb的主要几个类的分析,如何创建smartdb对象;
1 安装
如果是maven项目可以直接添加依赖如下
<dependency>
<groupId>net.1024lab</groupId>
<artifactId>smartdb</artifactId>
<version>1.2.0</version>
</dependency>
2 创建SmartDb对象
2.1 SmartDb的创建依赖于 数据源
SmartDb的使用建议依赖于数据源DataSource(当然不使用数据源也是可以的,但是每次操作db都去创建昂贵的connection是件很奢侈的事情),官方建议: 在使用SmartDb的时候优先使用数据源,比如DruidDataSource, C3p0DataSource,HikariDataSource等等
2.2 使用SmartDbBuilder类和 数据源 创建SmartDb
创建一个Mysql的SmartDb的代码如下:
SmartDb smartDb =
SmartDbBuilder.create()
//设置 写库 数据源 (必要)
.setMasterDataSource(writeDruidDataSource)
//设置 两个读库 数据源(非必要)
.setSlaveDataSource(readDruidDataSource1,readDruidDataSource2)
// 打印 info 级别sql
.setShowSql(true)
//设置数据库类型(必要)
.setSupportDatabaseType(SupportDatabaseType.MYSQL)
//设置支持spring (非必要,如果使用SmartDb作为Spring的默认ORM框架需要配置,如果不是默认ORM,一定不要配置)
.setSmartDbExtEnum(SmartDbExtEnum.SPRING5)
//表名与类名转换,将Class类名转为 数据库表 名字,假设数据库表名以 t_ 开头,小写下划线分隔,eg: t_order_item
.setTableNameConverter(cls -> "t_" + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, cls.getSimpleName()))
//列名字 转换 ,eg: 将 列名login_time 转为javabean字段 loginTime(必要)
.setColumnNameConverter(new CaseFormatColumnNameConverter(CaseFormat.LOWER_CAMEL, CaseFormat.LOWER_UNDERSCORE))
//添加 Sql执行时间 Filter拦截器 (非必要)
.addSmartDbFilter(new SqlExecutorTimeFilter())
.build();
具体方法解释:
- SmartDbBuilder.setMasterDataSource 方法表示 设置 主数据库,只能为一个;
- SmartDbBuilder.setSlaveDataSource 方法表示 设置 多个从数据库,可以为 0 到 N 个。0表示没有从库
- SmartDbBuilder.setTableNameConverter 方法表示 将Class类名转为 数据库表 名字,假设数据库表名以 t_ 开头,小写下划线分隔,eg:
t_order_item
, 类名OrderItem
- SmartDbBuilder.setColumnNameConverter 方法表示 数据库表 列名 与 Class的 属性名的 转换,这里推荐使用 guava的 CaseFormat进行配置,内部提供
CaseFormatColumnNameConverter
类支持 - addSmartDbFilter 方法表示 添加过滤器Filter,所有的Filter必须实现SmartDbFilter接口
2.3 使用SmartDbBuilder类和 jdbc参数 创建SmartDb(极不推荐)
SmartDb smartDb = SmartDbBuilder.create()
.setUrl("jdbc:mysql://127.0.0.1:3306/smartdb?useSSL=false&allowPublicKeyRetrieval=true")
.setDriverClassName("com.mysql.jdbc.Driver")
.setUsername("root")
.setPassword("root")
// 打印 info 级别sql
.setShowSql(true)
//设置数据库类型
.setSupportDatabaseType(SupportDatabaseType.MYSQL)
//设置支持spring
.setSmartDbExtEnum(SmartDbExtEnum.SPRING5)
//表名与类名转换,将Class类名转为 数据库表 名字,假设数据库表名以 t_ 开头,小写下划线分隔,eg: t_order_item
.setTableNameConverter(cls -> "t_" + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, cls.getSimpleName()))
//列名字 转换
.setColumnNameConverter(new CaseFormatColumnNameConverter(CaseFormat.LOWER_CAMEL, CaseFormat.LOWER_UNDERSCORE))
//添加 Sql执行时间 Filter拦截器
.addSmartDbFilter(new SqlExecutorTimeFilter())
.build();
极其不推荐以上方式来创建SmartDb,因为没有使用 连接池,每次操作都需要创建和关闭连接 是一个非常非常浪费和奢侈的事情。
3 SmartDb类的用途和思想
SmartDb是为了更方便操作数据库,方便的支持读写分离,所以一个SmartDb对象表示着 一个数据库集群 !!!
你没有看错,SmartDb的一个对象表示一个集群,集群里至少有 一个写库、大于等于0的读库。
SmartDb中含有多个SmartDbNode对象,源码如下:
class SmartDbImpl implements SmartDb {
// 随机获取slave库的索引
private AtomicInteger roundIndex = new AtomicInteger(-1);
// 主库 ( 写 库 )
private SmartDbNode master;
// 从库 ( 读 库 )
private List<SmartDbNode> slaves;
// smartdb 配置信息
private SmartDbConfig smartDbConfig;
// 是否存在 从库( 读 库 )
private boolean existSlave;
因为SmartDb表示一个集群,所以默认有如下操作 :
- 对数据库进行 update, delete, insert, replace等 修改的操作都是 默认操作 !写 !库。
- 对数据库进行 select查询的操作都是 默认操作 !读 !库。
3.1 默认对 写 库进行操作
所有的修改数据库操作都是在写(主)库上进行的,如下
smartDb.execute("update t_user set pwd = '123' where id = 1");
smartDb.insertSqlBuilder()...
smartDb.updateSqlBuilder()...
smartDb.deleteSqlBuilder()...
smartDb.replaceSqlBuilder()...
原理:源码如下, 可以清晰得看到,execute(增删改)调用的是master,即主库(写库)。
@Override
public int execute(String sql) {
return this.master.execute(sql);
}
@Override
public int execute(DeleteSqlBuilder deleteSqlBuilder) {
return this.master.execute(deleteSqlBuilder);
}
3.2 是默认对 读 库进行操作
所有的查询都是在读库进行的,而且是轮询查询读库
smartDb.queryList("selecct * from t_user",User.class);
原理:每次query的时候都先调用getSmartDbNode4Query()
方法,轮询获取读库(从库)。
public <T> T queryFirst(Class<T> cls, SelectSqlBuilder selectSqlBuilder) {
return this.getSmartDbNode4Query().queryFirst(cls, selectSqlBuilder);
}
public SmartDbNode getSmartDbNode4Query() {
if (this.existSlave) {
int round = this.roundIndex.incrementAndGet();
return this.slaves.get(Math.abs(round % this.slaves.size()));
} else {
return this.master;
}
}
如果想从写库 读取数据该怎么办呢??
直接调用getMaster()即可,是不是很方便呢~
List<userVO> userVOList = smartDb.getMaster().queryList("select * from t_user", User.class);
切记:默认查询操作都是从读库操作的!!,当然如果没有从库,则所有操作都是在主库上进行操作的 !
3 SmartDb类的介绍
SmartDb为最顶层的类,是一个接口,负责所有的入口操作,也是最最核心、使用频率最高的一个类,所有的操作都是以SmartDb以开始的,这样设计对使用者也是最方便的。
因为SmartDb为最顶层的接口,拥有所有操作数据库的方法,比如 增删查改、读写分离、ORM、等等。具体方法有:
方法名 | 方法作用 |
---|---|
execute | 执行Sql |
batch / batchInsert / batchInsertSelective | 批量操作 |
query | 查询 |
paginate | 分页查询 |
getTransaction | 获取带事务的SmartDb |
getMaster | 获取 写 数据库 |
getSlaves | 获取 所有的 从(读) 数据库 |
getSlave | 获取 某个指定的 从(读) 数据库 |
runTransaction | 执行一个事务操作 |
getRowConverter | 表中的行数据转换器 |
selectSqlBuilder | 获取一个select查询语句构器 |
insertSqlBuilder | 获取一个插入insert语句构造器 |
updateSqlBuilder | 获取一个更新update语句的构造器 |
deleteSqlBuilder | 获取一个删除delete语句的构造器 |
insert / insertSelective | ORM插入对象 |
update / updateSelective | ORM更新一个对象 |
delete | 根据ORM对象的 primary 删除对象 |
其他需要自己查看 | -- |
代码示例:
//构建SmartDb对象
SmartDb smartDb = build();
//以下所有的操作都是以SmartDb对象为开始
// ---------- ORM操作 ----------
//插入
smartDb.insert(userEntity);
smartDb.insertSelective(userEntity); // 非空字段插入
smartDb.batchInsert(userList);//批量插入
// 更新
smartDb.update(userEntity);
smartDb.updateSelective(userEntity); // 非空字段更新
// 删除
smartDb.delete(userEntity);//根据主键删除
// ---------- sql操作 ----------
smartDb.execute("update t_user set status = 1");
smartDb.queryList("select * from t_user ", UserVO.class);
// ---------- SmartDb 读写分离操作 ----------
//获取写库
SmartDb writeSmartDb = smartDb.getWriteSmartDb();
//将数据写入主库
writeSmartDb.insert(userEntity);
//进行主库其他操作
writeSmartDb.delete(userEntity);
writeSmartDb.updateSelective(userEntity);
// ---------- SmartDb UpdateSqlBuilder举例 ----------
smartDb.updateSqlBuilder()
.table("t_user")
.updateColumn("name = ?","smart")
.updateColumn(" login_time = now()")
.whereAnd("id = 1")
.execute();
//等等其他各类都是以SmartDb对象开始的
看了以上操作,有没有发现SmartDb操作起来还是非常简单的。