Skip to content

初识和创建SmartDb

简介SmartDb理念和思想,以及对SmartDb的主要几个类的分析,如何创建smartdb对象;

1 安装

如果是maven项目可以直接添加依赖如下

xml
<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的代码如下:

java
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(极不推荐)

java
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对象,源码如下:

java
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 默认对 库进行操作

所有的修改数据库操作都是在写(主)库上进行的,如下

java
smartDb.execute("update t_user set pwd = '123' where id = 1");
smartDb.insertSqlBuilder()...
smartDb.updateSqlBuilder()...
smartDb.deleteSqlBuilder()...
smartDb.replaceSqlBuilder()...

原理:源码如下, 可以清晰得看到,execute(增删改)调用的是master,即主库(写库)。

java
@Override
public int execute(String sql) {
    return this.master.execute(sql);
}

@Override
public int execute(DeleteSqlBuilder deleteSqlBuilder) {
    return this.master.execute(deleteSqlBuilder);
}

3.2 是默认对 库进行操作

所有的查询都是在读库进行的,而且是轮询查询读库

java
smartDb.queryList("selecct * from t_user",User.class);

原理:每次query的时候都先调用getSmartDbNode4Query()方法,轮询获取读库(从库)。

java
   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()即可,是不是很方便呢~

java
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 / insertSelectiveORM插入对象
update / updateSelectiveORM更新一个对象
delete根据ORM对象的 primary 删除对象
其他需要自己查看--

代码示例:

java
//构建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操作起来还是非常简单的。