<a name="imPZx"></a>
Foxnic-SQL (7) —— DAO 特性 : 执行 SQL 语句
<a name="dQiCk"></a>
概述
Foxnic-SQL 支持多种语句执行方式,包括直接执行SQL字符串、执行SQL对象,SQL对象自执行,多语句执行与批量执行。Foxnic-SQL 显著的特征是 DAO 对象既可以执行字符串的 SQL 语句,也可以执行对象化的SQL语句。<br />本文中的示例代码均可在 https://gitee.com/LeeFJ/foxnic-samples 项目中找到。
<a name="xq325"></a>
执行SQL字符串
SQL 执行最快捷、最能上手的方式,就是直接执行 SQL 字符串。DAO 对象可以执行不带参数或带参数的 SQL 字符串。如下代码所示:
1/** 2* 1、直接传入字符串的 SQL 语句,并执行 3* */ 4public static void demo1() { 5 // 通过 DBInstance 拿到 DAO 对象 6 DAO dao= DBInstance.DEFAULT.dao(); 7 // 生成 ID 8 String id= IDGenerator.getNanoId(8); 9 // 插入 10 String insert="insert into example_address (id, name, phone_number, address, region_type, region_location, create_by, " + 11 "create_time, update_by, update_time, deleted, delete_by, delete_time, version) " + 12 "VALUES (?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, 0, NULL, NULL, 1)"; 13 int i=dao.execute(insert,id,"leefj","13852562523","宁波","国内",new Date(),"110", new Date()); 14 Logger.info("插入 : "+i); 15 // 更新 16 i=dao.execute("update example_address set address=? where id=?","上海",id); 17 Logger.info("更新 : "+i); 18 // 删除 19 i=dao.execute("delete from example_address where id=?",id); 20 Logger.info("删除 : "+i); 21}
<a name="Lv8VG"></a>
执行 SQL 对象
DAO 对象同样支持对象话的SQL语句执行。SQL对象化的好处在之前的章节中已经介绍,感兴趣的读者可以查看 Foxnic-SQL 之前的文章《SQL表达式(Expr)》。示例代码如下所示:
1import com.github.foxnic.commons.busi.id.IDGenerator; 2import com.github.foxnic.dao.data.Rcd; 3import com.github.foxnic.sql.expr.Delete; 4import com.github.foxnic.sql.expr.Insert; 5import com.github.foxnic.sql.expr.Select; 6import com.github.foxnic.sql.expr.Update; 7import com.leefj.foxnic.sql.demo.config.DBInstance; 8 9import java.util.Date; 10 11public class CRUDBySQLDemo { 12 13 public static void main(String[] args) { 14 // 插入数据 15 String id=insertAddress("137771041252"); 16 System.out.println("addressId(Insert) = "+id); 17 // 按ID查询数据 18 Rcd address=queryAddress(id); 19 if(address!=null) { 20 System.out.println(address.toJSONObject()); 21 } 22 // 更新 23 if(id!=null) { 24 id=updateAddress(id,"13852562523"); 25 System.out.println("addressId(Update) = "+id); 26 } 27 // 删除 28 if(id!=null) { 29 id=deleteAddress(id); 30 System.out.println("addressId(Delete) = "+id); 31 } 32 } 33 34 /** 35 * 插入数据 36 * */ 37 public static String insertAddress(String phone) { 38 // 创建语句对象 39 Insert insert=new Insert("example_address"); 40 String id= IDGenerator.getSnowflakeIdString(); 41 // 设置值 42 insert.set("id",id) 43 .set("name","leefj") 44 // 如果是 null 则不连入SQL语句 45 .setIf("phone_number",phone) 46 .set("address","宁波") 47 .set("region_type","国内") 48 .set("create_time",new Date()) 49 // 设置数据库表达式 50 .setExpr("update_time","now()"); 51 // 输出语句 52 System.out.println(insert.getSQL()); 53 // 执行语句 54 Integer suc=DBInstance.DEFAULT.dao().execute(insert); 55 // 如果执行成功,返回ID,否则返回 null 56 if(suc==1) { 57 return id; 58 } else { 59 return null; 60 } 61 } 62 63 /** 64 * 查询 65 * */ 66 public static Rcd queryAddress(String id) { 67 68 // 创建语句对象 69 Select select=new Select("example_address"); 70 // 设置值 71 select.where().and("id=?",id); 72 // 输出语句 73 System.out.println(select.getSQL()); 74 // 执行语句 75 Rcd address=DBInstance.DEFAULT.dao().queryRecord(select); 76 // 如果执行成功,返回记录对象,否则返回 null 77 return address; 78 } 79 80 /** 81 * 更新 82 * */ 83 public static String updateAddress(String id,String phone) { 84 // 创建语句对象 85 Update update=new Update("example_address"); 86 // 设置值 87 update.setIf("phone_number",phone) 88 // 设置数据库表达式 89 .setExpr("update_time","now()") 90 .set("update_by","110") 91 .where().and("id=?",id); 92 // 输出语句 93 System.out.println(update.getSQL()); 94 // 执行语句 95 Integer suc=DBInstance.DEFAULT.dao().execute(update); 96 // 如果执行成功,返回ID,否则返回 null 97 if(suc==1) { 98 return id; 99 } else { 100 return null; 101 } 102 } 103 104 /** 105 * 删除 106 * */ 107 public static String deleteAddress(String id) { 108 // 创建语句对象 109 Delete delete=new Delete("example_address"); 110 // 设置条件 111 delete.where().and("id=?",id); 112 // 输出语句 113 System.out.println(delete.getSQL()); 114 // 执行语句 115 Integer suc=DBInstance.DEFAULT.dao().execute(delete); 116 // 如果执行成功,返回ID,否则返回 null 117 if(suc==1) { 118 return id; 119 } else { 120 return null; 121 } 122 } 123}
<a name="Lieux"></a>
ExecutableSQL 方式执行
ExecutableSQL 是一个接口,所有实现 ExecutableSQL 接口的 SQL 类都具备语句的执行能力。各种类型的 ExecutableSQL 可以通过 DAO 对象直接创建。示例如下:
1/** 2* 3、利用SQL对象的 ExecutableSQL 特性执行 3* */ 4public static void demo3() { 5 6 // 通过 DBInstance 拿到 DAO 对象 7 DAO dao= DBInstance.DEFAULT.dao(); 8 // 生成 ID 9 String id= IDGenerator.getNanoId(8); 10 11 // 插入:通过 DAO 创建一个与 DAO 绑定的 Insert 语句对象 12 int i=dao.insert("example_address") 13 .set("id",id) 14 .set("name","leefj") 15 // 如果是 null 则不连入SQL语句 16 .setIf("phone_number","13852562523") 17 .set("address","宁波") 18 .set("region_type","国内") 19 .set("create_time",new Date()) 20 // 设置数据库表达式 21 .setExpr("update_time","now()") 22 // 执行语句 23 .execute(); 24 Logger.info("插入 : "+i); 25 26 // 更新 27 i=dao.update("example_address").set("address","上海") 28 .where("id=?",id) 29 // 返回至顶层的 Update 语句对象 30 .top() 31 .execute(); 32 Logger.info("更新 : "+i); 33 34 // 删除 35 i=dao.delete("example_address") 36 .where("id=?",id) 37 // 返回至顶层的 Update 语句对象 38 .top() 39 .execute(); 40 Logger.info("删除 : "+i); 41}
<a name="fFavo"></a>
多语句执行
多语句执行顾名思义就是将多个语句放在一起执行,它们将在一个事务内执行,在不调用事务接口时,可以使用该方法以支持事务。示例代码如下:
1/** 2* 多个语句一起执行,这些语句在一个事务内 3* */ 4public static void demo1() { 5 6 // 通过 DBInstance 拿到 DAO 对象 7 DAO dao= DBInstance.DEFAULT.dao(); 8 // 生成 ID 9 String id= IDGenerator.getNanoId(8); 10 // 插入 11 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) " + 12 "VALUES (?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, 0, NULL, NULL, 1)", 13 id,"leefj","13852562523","宁波","国内",new Date(),"110", new Date()); 14 Expr update=new Expr("update example_address set address=? where id=?","上海",id); 15 Expr delete=new Expr("delete from example_address where id=?",id); 16 // 事务内同时执行多个语句,多参数并列 17 Integer result=dao.multiExecute(insert,update,delete); 18 // 把多个语句单独执行时影响的行数累加后返回 19 Logger.info("result = "+result); 20 21 // 产生一个 SQL 对象与字符串混合的 List 22 String sqlstr="delete from example_address where id='"+id+"'"; 23 List sqls= Arrays.asList(insert,update,delete,sqlstr); 24 // 事务内同时执行多个语句,传入列表, 25 result=dao.multiExecute(sqls); 26 // 把多个语句单独执行时影响的行数累加后返回 27 Logger.info("result = "+result); 28 29}
<a name="e6hJq"></a>
批量执行
批量执行是在大量插入或更新数据是使用的一种高性能的执行方式,这种方式可以显著提高SQL的执行效率。下面这个示例同时用常规方法和批量执行插入数据,批量的时间只有占常规的1/3。
1/** 2* 批量执行 3* */ 4public static void demo1() { 5 6 // 通过 DBInstance 拿到 DAO 对象 7 DAO dao= DBInstance.DEFAULT.dao(); 8 9 // 准备插入的 SQL 语句 10 String insert="insert into example_address " + 11 "(id, name, phone_number, address, region_type, region_location, create_by, create_time, " + 12 "update_by, update_time, deleted, delete_by, delete_time, version) " + 13 "values (?, ?, ?, ?, ?, null, null, ?, ?, ?, 0, null, null, 1)"; 14 // 性能日志对象 15 PerformanceLogger logger=new PerformanceLogger(); 16 // 性能采集埋点 17 logger.collect("常规插入开始"); 18 for (int i = 0; i < 100; i++) { 19 String id="batch-"+IDGenerator.getNanoId(6); 20 dao.execute(insert,id,"leefj","13852562523","宁波","国内",new Date(),"110", new Date()); 21 } 22 // 性能采集埋点 23 logger.collect("常规插入结束"); 24 // 性能采集埋点 25 logger.collect("批量插入开始"); 26 BatchParamBuilder paramBuilder=new BatchParamBuilder(); 27 for (int i = 0; i < 100; i++) { 28 String id="batch-"+IDGenerator.getNanoId(6); 29 paramBuilder.add(id,"leefj","13852562523","宁波","国内",new Date(),"110", new Date()); 30 } 31 int[] result=dao.batchExecute(insert,paramBuilder.getBatchList()); 32 // 性能采集埋点 33 logger.collect("批量插入结束"); 34 // 打印性能对比 35 logger.info("执行效率对比"); 36 // 输出结果 37 for (int i : result) { 38 System.out.println("结果:"+ i); 39 } 40}
性能对比日志:
┏━━━ PERFORMANCE [ 执行效率对比 , total = 4240 ] ━━━ ┣ point : 常规插入开始 ┣━ cost : 2961 ┣ point : 常规插入结束 ┣━ cost : 0 ┣ point : 批量插入开始 ┣━ cost : 1279 ┣ point : 批量插入结束 ┗━━━ PERFORMANCE [ 执行效率对比 , total = 4240 ] ━━━
<a name="PV8XF"></a>
<a name="YZs52"></a>
小结
本节主要介绍了如何使用 Foxnic-SQL 的 DAO 对象使用不同的姿势执行 SQL 语句。本节中展示的例子主要目的是抛砖引玉,为了方便不同场景的调用,DAO 还提供了若干重载方法,以不同的参数形式去执行语句。
<a name="VZBg5"></a>
相关项目
https://gitee.com/LeeFJ/foxnic<br /> https://gitee.com/LeeFJ/foxnic-web<br /> https://gitee.com/lank/eam<br /> https://gitee.com/LeeFJ/foxnic-samples
