数据库访问

栏目:云苍穹知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

数据库访问

# 1 简介 数据库访问是平台提供的访问数据库的接口DB。它的基本用法与JDBC相似,但是它提供更加统一方便的接口。在使用DB访问数据库的时候统一使用KSQL语法。在苍穹系统中,支持每个应用使用独立的数据库,SQL在哪个数据库上执行是通过DBRoute来路由。DB屏蔽了物理数据库信息,用DBRoute对应具体的物理库,由mc的数据中心管理进行配置。DBRoute内置了常用的routeKey,也可以通过DBRoute.of("routeKey")来构造。表单的routeKey在设计时已自动指定,在同一个应用下的表单routeKey相同。 # 2 应用场景 在需要通过SQL访问的场景下必须使用DB来访问数据库。 # 3 接口说明 数据库访问DB相关接口定义和实现存在于bos-dbengine-1.0.jar中。对于使用者来说只需要调用kd.bos.db.DB类中的方法即可。 ## 3.1 接口列表 | 方法 | 说明 | | - | - | | query | 查询 | | queryDataSet | 查询(返回DataSet) | | update | 插入、更新或删除 | | execute | 执行任何类型的SQL | | executeBatch | 批量执行任何类型的SQL | | timeout | 设置超时时间 | | getDBType | 获取数据库类型 | | exitsTable | 判断表是否存在 | | exitsIndex | 判断表索引是否存在 | | getPrimaryKeys | 获取表主键 | | getFieldInfo | 获取表的字段信息 | | getIndexInfo | 获取表的索引信息 | | isXDBEnable | 是否启用了xdb引擎(水平分表) | | isSplittingReadEnable | 是否开启读写分离 | | isSplittingAutoReadWrite | 是否开启自动读写模式 | | getWrittenRouteKey | 获取当前事务已写的库路由标识 | ## 3.2 接口详情 ### query + **功能描述** 查询数据库操作。 + **方法** ```java public static <T> T query(DBRoute dbRoute, String sql, ResultSetHandler<T> rh) public static <T> T query(DBRoute dbRoute, String sql, Object[] params, ResultSetHandler<T> rh) ``` + **参数说明** | 参数 | 类型 | 说明 | | - | - | - | | dbRoute | DBRoute | 数据库路由 | | sql | String | 查询SQL语句 | | params | Object[] | SQL参数 | | rh | ResultSetHandler\<T> | jdbc结果集ResultSet处理器 | + **返回值** 返回ResultSet处理器返回的结果。 + **示例代码** ```java // 不带参数 String sql = "SELECT * FROM table;" DB.query(DBRoute.basedata, sql, rs -> { return rs.next(); }); // 带参数 String sql = "SELECT * FROM table WHERE fid=?;" DB.query(DBRoute.basedata, sql, new Object[]{"xxxxxxxx"}, rs -> { return rs.next(); }); ``` ### queryDataSet + **功能描述** 查询数据库操作(返回DataSet)。 + **方法** ```java public static DataSet queryDataSet(String algoKey, DBRoute dbRoute, String sql) public static DataSet queryDataSet(String algoKey, DBRoute dbRoute, String sql, Object[] params) ``` + **参数说明** | 参数 | 类型 | 说明 | | - | - | - | | algoKey | String | algo标识 | | dbRoute | DBRoute | 数据库路由 | | sql | String | 查询SQL语句 | | params | Object[] | SQL参数 | > 参数algoKey用于跟踪性能,当前执行的时间将被记录到指标系统。这个值,应能有效定位到代码, 如=类名+方法,至少含类名。 + **返回值** 返回DataSet数据集(它是根据查询结果ResultSet包装而来)。 + **示例代码** ```java // 不带参数 String sql = "SELECT * FROM table;" DataSet dataSet = DB.queryDataSet(this.getClass.getName(), DBRoute.basedata, sql); // 带参数 String sql = "SELECT * FROM table WHERE fid=?;" DataSet dataSet = DB.queryDataSet(this.getClass.getName(), DBRoute.basedata, sql, new Object[]{"xxxxxxxx"}); ``` ### update + **功能描述** 插入、更新或删除数据库操作。 + **方法** ```java public static int update(DBRoute dbRoute, String sql) public static int update(DBRoute dbRoute, String sql, Object[] params) ``` + **参数说明** | 参数 | 类型 | 说明 | | - | - | - | | dbRoute | DBRoute | 数据库路由 | | sql | String | 查询SQL语句 | | params | Object[] | SQL参数 | + **返回值** 更新数据的行数。 + **示例代码** ```java // 不带参数 String sql = "UPDATE t_xxx SET field=xxx WHERE fid=xxx;" DB.update(DBRoute.basedata, sql); // 带参数 String sql = "UPDATE t_xxx SET field=? WHERE fid=?;" DB.update(DBRoute.basedata, sql, new Object[]{"xxx", "xxx"}); ``` ### execute + **功能描述** 执行任何类型的SQL。 + **方法** ```java public static boolean execute(DBRoute dbRoute, String sql) public static boolean execute(DBRoute dbRoute, String sql, Object[] params) ``` + **参数说明** | 参数 | 类型 | 说明 | | - | - | - | | dbRoute | DBRoute | 数据库路由 | | sql | String | 查询SQL语句 | | params | Object[] | SQL参数 | + **返回值** 是否执行成功。 + **示例代码** ```java // 不带参数 String sql = "UPDATE t_xxx SET field=xxx WHERE fid=xxx;" DB.execute(DBRoute.basedata, sql); // 带参数 String sql = "UPDATE t_xxx SET field=? WHERE fid=?;" DB.execute(DBRoute.basedata, sql, new Object[]{"xxx", "xxx"}); ``` ### executeBatch + **功能描述** 批量执行任何类型的SQL。 + **方法** ```java public static boolean execute(DBRoute dbRoute, String sql, List<Object[]> paramsList) ``` + **参数说明** | 参数 | 类型 | 说明 | | - | - | - | | dbRoute | DBRoute | 数据库路由 | | sql | String | 查询SQL语句 | | paramsList | List<Object[]> | SQL参数列表 | + **返回值** 批量执行的数量。 + **示例代码** ```java String sql = "UPDATE t_xxx SET field=? WHERE fid=?;"; List<Object[]> paramsList = new ArrayList(); Object[] params = new Object[]{"xxx", "xxx"}; paramsList.add(params); int[] executeBatch = DB.executeBatch(DBRoute.basedata, sql, paramsList); ``` ### timeout + **功能描述** 设置查询超时时间。 + **方法** ```java public static QueryTimeout timeout(int seconds) ``` + **参数说明** | 参数 | 类型 | 说明 | | - | - | - | | seconds | int | 超时时间(秒) | + **返回值** 查询超时对象。 + **示例代码** ```java try(DB.timeout(10)) { DB.query(...); } ``` > 默认情况下,执行SQL超时时间为300秒(可通过在MC配置db.query.timeout=300来修改)。timeout方法允许开发者自定义查询超时时间。执行超过query time,则执行中断并抛出SQLException。 # 4 注意事项 ## 4.1 ResultSetHandler ```java public interface ResultSetHandler<T> { T handle(ResultSet rs) throws Exception; } ``` ResultSetHandler是用于处理JDBC结果集ResultSet的一个自定义的处理器接口。使用者可以实现该接口方法来实现结果集的处理逻辑,实现的方法中的返回值也是DB.query方法的返回值。 ## 4.2 优化in参数转临时表 在数据库操作中,由于数据库对in参数有长度限制,所以我们需要对in参数转临时表处理。 当启用in优化,in的参数个数>=优化阀值时,将对过滤条件信息优化。in参数个数超过orm.opt.in.maxsize,则系统抛异常,异常信息形如: > in query params length over the maximum:510000 > 500000 + in优化参数配置 ```properties # 优化阀值:默认1000 orm.opt.in.threshold=1000 # in允许的最大个数:默认50w orm.opt.in.maxsize=500000 ``` 为了优化in参数转临时表,在DB中提供了专门的in参数转临时表数据库操作接口。 ```java public static boolean execute(DBRoute dbRoute, SqlBuilder sb) public static <T> T query(DBRoute dbRoute, SqlBuilder sb, ResultSetHandler<T> rh) public static DataSet queryDataSet(String algoKey, DBRoute dbRoute, SqlBuilder sb) ``` 这些接口与其他的数据库操作接口使用并无太大差别。在有需要in参数转临时表时,使用上述三个接口,只是这些接口需要使用SqlBuilder来创建SQL语句。如下例所示: ```java public void testDBQuerySqlBuilder(){ //设置启用阀值 System.setProperty("orm.opt.in.threshold", "100"); List<Object> pkIds = getPKs(100); //oraginal sql= SELECT FID FROM T_SEC_USER WHERE FID IN(?,?,?...) ORDER BY FID DESC SqlBuilder sqlBuilder = new SqlBuilder(); sqlBuilder.append("SELECT FID FROM T_SEC_USER WHERE"); sqlBuilder.appendIn("FID", pkIds); sqlBuilder.append("ORDER BY FID DESC"); DataSet ds = DB.queryDataSet("test_sqlBuilder", DBRoute.basedata, sqlBuilder); } public List<Object> getPKs(int size){ String sql = "SELECT TOP " + size + ",0 FID FROM T_SEC_USER"; DataSet ds = DB.queryDataSet("InQueryToTempTable_getPKS", DBRoute.base, sql); List<Object> list = new ArrayList<>(); for(Row r:ds){ Object o = r.get(0); list.add(o); } return list; } ``` ## 4.3 空格和0长度串 数据库字段若为字符串类型,则不允许保存null和0长度的字符串,无值默认用" "。 用户仍正常使用,存取值由DB层处理转换: + 保存:参数传入"“或null,则保存为” "。 必须通过参数设置才会自动转换。(ParameterSetter) + 查询:" “转为”"。 通过DB结果集转换。(WrapCloseResultSet) 控制是否转换的参数:db.spaceAsEmptyString,默认值为true。 ## 4.4 bigint类型值 ksql bigint类型的字段,取值返回类型统一 为long。 ## 4.5 boolean类型参数 参数传boolean类型,则在jdbc参数设置时自动转为’0’或’1’。(对应的存储字段类型应为char(1)) > 注意:在ResultSet中取值仍为’0’或’1’,在ORM的DynamicObject中的值则为true或false。 ## 4.6 禁止新建线程访问 **若需要开启新线程,用ThreadPools启动。自行new Thread被禁止使用DB访问数据库。** ## 4.7 开发环境的SQL日志 在开发环境,如果info级别的日志被关闭,则可以通过以下代码,在控制台输出。 ```java // 启动前开启DB日志 (加在启动类里) System.setProperty("db.sql.out", "true"); // 运行期前开启DB日志(仅用于调试,不要在产品中使用,会导致日志配置失效) DB.setSqlOut(true); ``` ***SQL跟踪调试*** 1. 在AbstractDBImpl.logSQL方法中设置断点。 2. 为方便对sql进行编码式过滤调试,提供了自定义SqlLogger。在启动类 start之前,增加InitListener,设置SqlLogger(见下面代码),把SQL再次log出来过滤。不受db.sql.out参数的控制,只要设置了SqlLogger,日志必输出,不影响原有的日志输出。 ```java webInit.addInitListener(new InitListener() { @Override public void started() { DB.setSqlLogger(new SqlLogger() { @Override public void log(String sql, Object...params) { if (sql.toLowerCase().indexOf("t_sec_user") != -1) { // debug,在这里设置断点进行调试。 System.err.println("### 用户表sql: " + sql); } else { System.out.println("### SQL: " + sql); } } }); } }); webInit.start(); ``` ***上例输出*** > \### 用户表sql: /*ORM*/ SELECT B.fdptid “entryentity.dpt.id”FROM t_SEC_User A LEFT JOIN t_SEC_UserPosition B ON B.FId=A.FId WHERE A.FId = ?

数据库访问

# 1 简介数据库访问是平台提供的访问数据库的接口DB。它的基本用法与JDBC相似,但是它提供更加统一方便的接口。在使用DB访问数据库的时候...
点击下载文档
上一篇:数据库事务下一篇:日志
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息