Foxnic-SQL (7) —— DAO 特性 : 执行 SQL 语句
概述
Foxnic-SQL 支持多种语句执行方式,包括直接执行SQL字符串、执行SQL对象,SQL对象自执行,多语句执行与批量执行。Foxnic-SQL 显著的特征是 DAO 对象既可以执行字符串的 SQL 语句,也可以执行对象化的SQL语句。
本文中的示例代码均可在 https://gitee.com/LeeFJ/foxnic-samples 项目中找到。
执行SQL字符串
SQL 执行最快捷、最能上手的方式,就是直接执行 SQL 字符串。DAO 对象可以执行不带参数或带参数的 SQL 字符串。如下代码所示:
/**
* 1、直接传入字符串的 SQL 语句,并执行
* */
public static void demo1() {
// 通过 DBInstance 拿到 DAO 对象
DAO dao= DBInstance.DEFAULT.dao();
// 生成 ID
String id= IDGenerator.getNanoId(8);
// 插入
String insert="insert into example_address (id, name, phone_number, address, region_type, region_location, create_by, " +
"create_time, update_by, update_time, deleted, delete_by, delete_time, version) " +
"VALUES (?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, 0, NULL, NULL, 1)";
int i=dao.execute(insert,id,"leefj","13852562523","宁波","国内",new Date(),"110", new Date());
Logger.info("插入 : "+i);
// 更新
i=dao.execute("update example_address set address=? where id=?","上海",id);
Logger.info("更新 : "+i);
// 删除
i=dao.execute("delete from example_address where id=?",id);
Logger.info("删除 : "+i);
}
执行 SQL 对象
DAO 对象同样支持对象话的SQL语句执行。SQL对象化的好处在之前的章节中已经介绍,感兴趣的读者可以查看 Foxnic-SQL 之前的文章《SQL表达式(Expr)》。示例代码如下所示:
import com.github.foxnic.commons.busi.id.IDGenerator;
import com.github.foxnic.dao.data.Rcd;
import com.github.foxnic.sql.expr.Delete;
import com.github.foxnic.sql.expr.Insert;
import com.github.foxnic.sql.expr.Select;
import com.github.foxnic.sql.expr.Update;
import com.leefj.foxnic.sql.demo.config.DBInstance;
import java.util.Date;
public class CRUDBySQLDemo {
public static void main(String[] args) {
// 插入数据
String id=insertAddress("137771041252");
System.out.println("addressId(Insert) = "+id);
// 按ID查询数据
Rcd address=queryAddress(id);
if(address!=null) {
System.out.println(address.toJSONObject());
}
// 更新
if(id!=null) {
id=updateAddress(id,"13852562523");
System.out.println("addressId(Update) = "+id);
}
// 删除
if(id!=null) {
id=deleteAddress(id);
System.out.println("addressId(Delete) = "+id);
}
}
/**
* 插入数据
* */
public static String insertAddress(String phone) {
// 创建语句对象
Insert insert=new Insert("example_address");
String id= IDGenerator.getSnowflakeIdString();
// 设置值
insert.set("id",id)
.set("name","leefj")
// 如果是 null 则不连入SQL语句
.setIf("phone_number",phone)
.set("address","宁波")
.set("region_type","国内")
.set("create_time",new Date())
// 设置数据库表达式
.setExpr("update_time","now()");
// 输出语句
System.out.println(insert.getSQL());
// 执行语句
Integer suc=DBInstance.DEFAULT.dao().execute(insert);
// 如果执行成功,返回ID,否则返回 null
if(suc==1) {
return id;
} else {
return null;
}
}
/**
* 查询
* */
public static Rcd queryAddress(String id) {
// 创建语句对象
Select select=new Select("example_address");
// 设置值
select.where().and("id=?",id);
// 输出语句
System.out.println(select.getSQL());
// 执行语句
Rcd address=DBInstance.DEFAULT.dao().queryRecord(select);
// 如果执行成功,返回记录对象,否则返回 null
return address;
}
/**
* 更新
* */
public static String updateAddress(String id,String phone) {
// 创建语句对象
Update update=new Update("example_address");
// 设置值
update.setIf("phone_number",phone)
// 设置数据库表达式
.setExpr("update_time","now()")
.set("update_by","110")
.where().and("id=?",id);
// 输出语句
System.out.println(update.getSQL());
// 执行语句
Integer suc=DBInstance.DEFAULT.dao().execute(update);
// 如果执行成功,返回ID,否则返回 null
if(suc==1) {
return id;
} else {
return null;
}
}
/**
* 删除
* */
public static String deleteAddress(String id) {
// 创建语句对象
Delete delete=new Delete("example_address");
// 设置条件
delete.where().and("id=?",id);
// 输出语句
System.out.println(delete.getSQL());
// 执行语句
Integer suc=DBInstance.DEFAULT.dao().execute(delete);
// 如果执行成功,返回ID,否则返回 null
if(suc==1) {
return id;
} else {
return null;
}
}
}
ExecutableSQL 方式执行
ExecutableSQL 是一个接口,所有实现 ExecutableSQL 接口的 SQL 类都具备语句的执行能力。各种类型的 ExecutableSQL 可以通过 DAO 对象直接创建。示例如下:
/**
* 3、利用SQL对象的 ExecutableSQL 特性执行
* */
public static void demo3() {
// 通过 DBInstance 拿到 DAO 对象
DAO dao= DBInstance.DEFAULT.dao();
// 生成 ID
String id= IDGenerator.getNanoId(8);
// 插入:通过 DAO 创建一个与 DAO 绑定的 Insert 语句对象
int i=dao.insert("example_address")
.set("id",id)
.set("name","leefj")
// 如果是 null 则不连入SQL语句
.setIf("phone_number","13852562523")
.set("address","宁波")
.set("region_type","国内")
.set("create_time",new Date())
// 设置数据库表达式
.setExpr("update_time","now()")
// 执行语句
.execute();
Logger.info("插入 : "+i);
// 更新
i=dao.update("example_address").set("address","上海")
.where("id=?",id)
// 返回至顶层的 Update 语句对象
.top()
.execute();
Logger.info("更新 : "+i);
// 删除
i=dao.delete("example_address")
.where("id=?",id)
// 返回至顶层的 Update 语句对象
.top()
.execute();
Logger.info("删除 : "+i);
}
多语句执行
多语句执行顾名思义就是将多个语句放在一起执行,它们将在一个事务内执行,在不调用事务接口时,可以使用该方法以支持事务。示例代码如下:
/**
* 多个语句一起执行,这些语句在一个事务内
* */
public static void demo1() {
// 通过 DBInstance 拿到 DAO 对象
DAO dao= DBInstance.DEFAULT.dao();
// 生成 ID
String id= IDGenerator.getNanoId(8);
// 插入
Expr insert=new Expr("insert into example_address (id, name, phone_number, address, region_type, region_location, create_by, create_time, update_by, update_time, deleted, delete_by, delete_time, version) " +
"VALUES (?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, 0, NULL, NULL, 1)",
id,"leefj","13852562523","宁波","国内",new Date(),"110", new Date());
Expr update=new Expr("update example_address set address=? where id=?","上海",id);
Expr delete=new Expr("delete from example_address where id=?",id);
// 事务内同时执行多个语句,多参数并列
Integer result=dao.multiExecute(insert,update,delete);
// 把多个语句单独执行时影响的行数累加后返回
Logger.info("result = "+result);
// 产生一个 SQL 对象与字符串混合的 List
String sqlstr="delete from example_address where id='"+id+"'";
List sqls= Arrays.asList(insert,update,delete,sqlstr);
// 事务内同时执行多个语句,传入列表,
result=dao.multiExecute(sqls);
// 把多个语句单独执行时影响的行数累加后返回
Logger.info("result = "+result);
}
批量执行
批量执行是在大量插入或更新数据是使用的一种高性能的执行方式,这种方式可以显著提高SQL的执行效率。下面这个示例同时用常规方法和批量执行插入数据,批量的时间只有占常规的1/3。
/**
* 批量执行
* */
public static void demo1() {
// 通过 DBInstance 拿到 DAO 对象
DAO dao= DBInstance.DEFAULT.dao();
// 准备插入的 SQL 语句
String insert="insert into example_address " +
"(id, name, phone_number, address, region_type, region_location, create_by, create_time, " +
"update_by, update_time, deleted, delete_by, delete_time, version) " +
"values (?, ?, ?, ?, ?, null, null, ?, ?, ?, 0, null, null, 1)";
// 性能日志对象
PerformanceLogger logger=new PerformanceLogger();
// 性能采集埋点
logger.collect("常规插入开始");
for (int i = 0; i < 100; i++) {
String id="batch-"+IDGenerator.getNanoId(6);
dao.execute(insert,id,"leefj","13852562523","宁波","国内",new Date(),"110", new Date());
}
// 性能采集埋点
logger.collect("常规插入结束");
// 性能采集埋点
logger.collect("批量插入开始");
BatchParamBuilder paramBuilder=new BatchParamBuilder();
for (int i = 0; i < 100; i++) {
String id="batch-"+IDGenerator.getNanoId(6);
paramBuilder.add(id,"leefj","13852562523","宁波","国内",new Date(),"110", new Date());
}
int[] result=dao.batchExecute(insert,paramBuilder.getBatchList());
// 性能采集埋点
logger.collect("批量插入结束");
// 打印性能对比
logger.info("执行效率对比");
// 输出结果
for (int i : result) {
System.out.println("结果:"+ i);
}
}
性能对比日志:
┏━━━ PERFORMANCE [ 执行效率对比 , total = 4240 ] ━━━ ┣ point : 常规插入开始 ┣━ cost : 2961 ┣ point : 常规插入结束 ┣━ cost : 0 ┣ point : 批量插入开始 ┣━ cost : 1279 ┣ point : 批量插入结束 ┗━━━ PERFORMANCE [ 执行效率对比 , total = 4240 ] ━━━
小结
本节主要介绍了如何使用 Foxnic-SQL 的 DAO 对象使用不同的姿势执行 SQL 语句。本节中展示的例子主要目的是抛砖引玉,为了方便不同场景的调用,DAO 还提供了若干重载方法,以不同的参数形式去执行语句。
相关项目
https://gitee.com/LeeFJ/foxnic
https://gitee.com/LeeFJ/foxnic-web
https://gitee.com/lank/eam
https://gitee.com/LeeFJ/foxnic-samples