Solon 3.0 引入了新的 SqlUtils 用于数据库基础操作,SqlUtils 是对 JDBC 较为原始的封装,采用了 Utils API 的风格,极为反普归真。 特性有:
- 支持事务管理
- 支持多数据源
- 支持流式输出
- 支持批量执行
- 支持存储过程
一、概述
SqlUtils 是一个轻量的数据库操作框架,采用 Utils API 风格,简单灵活,易于阅读和维护,支持编写复杂的SQL。对于不适合使用复杂的 ORM 框架,或者需要编写复杂的 SQL 的场景,可以使用 SqlUtils 来操作数据库。
二、引入 SqlUtils
-
gradle 依赖
implementation 'org.noear:solon-data-sqlutils'
-
maven 依赖
<dependency> <groupId>org.noear</groupId> <artifactId>solon-data-sqlutils</artifactId> </dependency>
三、配置数据源
配置数据源(具体参考:《数据源的配置与构建》)
yml
solon.dataSources:
rock!:
class: "com.zaxxer.hikari.HikariDataSource"
jdbcUrl: jdbc:mysql://localhost:3306/rock?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: 123456
之后就可以按数据源名注入 SqlUtils 了(带 !
结尾的数据源名,为默认)
java
@Component
public class DemoService {
@Inject //默认数据源名
SqlUtils sqlUtils;
}
四、查询操作
查数量:
java
public Long findCount() throws SQLException {
return sqlUtils.selectValue("select count(*) from appx where app_id = ?", id);
}
按照主键查数据:
java
public Appx findDataById(Integer id) throws SQLException {
return sqlUtils.selectRow("select * from appx where app_id = ?", id)
.toBean(Appx.class);
}
按照自定义查询条件查数据:
java
public List<Appx> findDataByGroup(Integer group_id) throws SQLException {
return sqlUtils.selectRowList("select * from appx where group_id = ?", group_id)
.toBeanList(Appx.class);
}
以上几种查询方式,查询条件中的变量使用的是占位符(SqlUtils 只支持占位符),也比较简单。复杂的查询怎么办?比如管理后台的条件统计,可以先使用构建器:
java
public List<Appx> findDataStat(int group_id, String channel, int scale) throws SQLException {
SqlBuilder builder = new SqlBuilder();
builder.append("select group_id, sum(amount) amount from appx ")
.append("where group_id = ? group by group_id", group_id);
builder.appendIf(channel != null, " and title channel ?", channel + "%");
if(scale > 10){
builder.append(" and scale = ?", scale);
}
return sqlUtils.selectRowList(builder.getSql(), builder.getArgs())
.toBeanList(Appx.class);
}
管理后台常见的分页查询:
java
public void findDataPage(int group_id, String channel) throws SQLException {
SqlBuilder builder = new SqlBuilder()
.append(" from appx where group_id = ?", group_id)
.appendIf(channel != null, " and title channel ?", channel + "%");
//备份
builder.backup();
builder.insert("select *");
builder.append(" limit ?,?", 10,10); //分页获取列表
//查询列表
List<Appx> list = sqlUtils.selectRowList(builder.getSql(), builder.getArgs())
.toBeanList(Appx.class);
//回滚(可以复用备份前的代码构建)
builder.restore();
builder.insert("select count(*)");
//查询总数
Long total = sqlUtils.selectValue(builder.getSql(), builder.getArgs());
}
五、流式查询操作
支持 fetchSize 参数
java
public void findDataAll(Integer group_id) throws SQLException {
try (RowIterator iterator = sqlUtils.selectRowIterator("select * from appx where group_id = ?", 100, group_id)) {
while (iterator.hasNext()){
Appx app = iterator.next().toBean(Appx.class);
//....
}
}
}
六、插入操作
单条插入:
java
public void addData(int id) throws SQLException {
return sqlUtils.insert("insert appx(app_id) values(?)", id);
}
单条插入并返回Key:
java
public void addData(int id) throws SQLException {
return sqlUtils.insertReturnKey("insert appx(app_id) values(?)", id);
}
批量插入:
java
public void addDataBatch() throws SQLException {
List<Object[]> argsList = new ArrayList<>();
argsList.add(new Object[]{1});
argsList.add(new Object[]{2});
argsList.add(new Object[]{3});
argsList.add(new Object[]{4});
argsList.add(new Object[]{5});
sqlUtils.executeBatch("insert appx(app_id) values(?)", argsList);
}
六、执行操作(更新或删除)
支持事务控制
java
@Tran
public void delData(int id) throws SQLException {
sqlUtils.execute("delete from appx where app_id=?", id);
}
@Tran
public void updateData(int id) throws SQLException {
sqlUtils.execute("update appx set group_id=? where app_id=?", 2, id);
}
七、存储过程操作
查询操作
java
public Appx findDataById(int id) throws SQLException {
return sqlUtils.selectRow("{call findDataById(?)}", id).toBean(Appx.class);
}
删除操作
java
public int findDataById(int id) throws SQLException {
return sqlUtils.execute("{call delDataById(?)}", id);
}
八、总结
通过上述的示例,可以看到基本的数据库操作都可以用 SqlUtils 实现,避免了复杂的ORM框架的使用,切操作要比ORM框架简单灵活的多。Utils API 的风格也更容易编写和阅读。