核心源码就在sharding-jdbc-core模块的com.dangdang.ddframe.rdb.sharding.rewrite目录下,包含两个文件SQLBuilder和SQLRewriteEngine 即查询结果列的重写--需要由于ordre by或者group by需要增加一些结果列); public SQLBuilder rewrite(final boolean isRewriteLimit) { SQLBuilder result = new SQLBuilder(); if (sqlTokens.isEmpty()) { result.appendLiterals , count, sqlTokens, beginPosition);} rowCount重写分析 private void appendLimitRowCount(final SQLBuilder sqlBuilder , count, sqlTokens, beginPosition);} appendRest分析 private void appendRest(final SQLBuilder sqlBuilder
<Object>(); protected Map<String, Object> paramMap = new HashMap<String, Object>(); public SqlBuilder appendSql(String sql) { sqlBuf.append(sql); return this; } public SqlBuilder ; values.add(value); return this; } public SqlBuilder appendValues(Object[] == ',') { sqlBuf.setCharAt(last, ')'); } return this; } public SqlBuilder append(" = :").append(param); paramMap.put(param, value); return this; } public SqlBuilder
SQL构建器组件封装下面是一个使用StringBuilder实现的SQL构建器组件:public class SQLBuilder { private final StringBuilder sql = new StringBuilder(); public SQLBuilder select(String... columns) { sql.append("SELECT 1) { sql.append(", "); } } return this; } public SQLBuilder 使用SQL构建器public class SQLBuilderExample { public static void main(String[] args) { SQLBuilder builder = new SQLBuilder(); // 构建SQL查询 String sql = builder.select("id", "name
生成的 SQL 语句会追加到 sqlBuilder 中。 最后,sqlBuilder 的内容会写入 HTTP 响应,允许用户下载 SQL 文件。 public void exportBatchJobs(HttpServletResponse response) { try { StringBuilder sqlBuilder executorService.submit(() -> { try { downloadTable(tableName, sqlBuilder String.class); } /** * 导出指定表SQL * * @param tableName * 表明 * @param sqlBuilder * @since 2023/8/10 */ public void downloadTable(String tableName, StringBuilder sqlBuilder
) { SQLBuilder result = new SQLBuilder(); if (sqlTokens.isEmpty()) { result.appendLiterals 当路由结果为单分片时无需重写 */ private void appendLimitOffsetToken(final SQLBuilder sqlBuilder, final OffsetToken // SQLRewriteEngine.java private void appendLimitRowCount(final SQLBuilder sqlBuilder, final RowCountToken 处理分页 // SQL 重写 SQLBuilder sqlBuilder = rewriteEngine.rewrite(! cartesianTableReference, final SQLBuilder sqlBuilder) { return sqlBuilder.toSQL(getTableTokens(cartesianTableReference
简单到没朋友 public String getPageSql(String sql, Page page, CacheKey pageKey) { StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14); sqlBuilder.append(sql); if (page.getStartRow () == 0) { sqlBuilder.append(" LIMIT ? "); } else { sqlBuilder.append(" LIMIT ?, ? "); } return sqlBuilder.toString(); } 步骤5:封装结果 还是把查询到的结果放到TheadLocal中的page对象中,然后返回
queryByPrimaryKey(String tableName, String primaryKey, Object value, Class<T> clazz) { StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.append(select); sqlBuilder.append(star); sqlBuilder.append(from ); sqlBuilder.append(tableName); if (null == primaryKey || 0 >= primaryKey.length()) { primaryKey = "id"; } sqlBuilder.append(where); sqlBuilder.append(primaryKey); sqlBuilder.append(" = ? limit 1 "); log.debug("querySql-{}",sqlBuilder.toString()); return this.querySingleObj(clazz, sqlBuilder.toString
= new StringBuilder(sql.length() + 14); sqlBuilder.append(sql); if (page.getStartRow () == 0) { sqlBuilder.append(" LIMIT ? "); } else { sqlBuilder.append(" LIMIT ?, ? () > 0) { sqlBuilder.append(" ) TMP_PAGE WHERE ROWNUM <= ? "); } return sqlBuilder.toString(); } 其他数据库分页操作类似。
Override public String getPageSql(String sql, Page page, CacheKey pageKey) { StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14); sqlBuilder.append(sql); if (page.getStartRow () == 0) { sqlBuilder.append(" LIMIT ? "); } else { sqlBuilder.append(" LIMIT ?, ? "); } pageKey.update(page.getPageSize()); return sqlBuilder.toString(); }
; if (lastN > 0) { sqlBuilder.append(" LIMIT ?") ; } return sqlBuilder.toString(); } private void checkAndCreateTable() throws SQLException { ; if (lastN > 0) { sqlBuilder.append(" AND ROWNUM <= ?") ; } sqlBuilder.append(")"); return sqlBuilder.toString(); }}OracleChatMemory继承了JdbcChatMemory ; return sqlBuilder.toString(); }}SqlServerChatMemory继承了JdbcChatMemory,其jdbcType为sqlserver,它还额外覆盖了
jdbcTemplate.queryForList("SHOW CREATE TABLE " + tableName); // 拼接SQL插入语句 StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.append(tableStructure.get(0).get("Create Table")).append(" ); String values = valuesBuilder.substring(0, valuesBuilder.length() - 2); sqlBuilder.append HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + tableName+".sql"); response.getWriter().write(sqlBuilder.toString
SqlBuilder 这不是一个接口,而是一个工具类,它包含了一系列静态方法来帮助构建动态 SQL 语句的各个部分,如 select(), from(), where(), orderBy() 等。 使用 MyBatis Dynamic SQL 时,开发者通常会通过自动生成的 DynamicSqlSupport 类来引用表和字段,然后使用 SqlBuilder 类和相关的条件构建器来构建 SQL 语句 查询条件类(UserCriteria.java): import org.mybatis.dynamic.sql.SqlBuilder; import java.util.Optional; public // Other getters and setters... } 查询构建器类(UserSqlBuilder.java): import org.mybatis.dynamic.sql.SqlBuilder 使用SqlBuilder提供的方法来处理可选条件,例如使用isEqualTo结合Optional.orElse或Optional.ifPresent。
这篇文章源于【死磕Sharding-jdbc】-----重写的遗留问题,相关sharding-jdbc源码如下: private void appendLimitRowCount(final SQLBuilder sqlBuilder, final RowCountToken rowCountToken, final int count, final List<SQLToken> sqlTokens, final group by user_id order by sum(score) desc limit 5",那么limit 5需要重写为limit Integer.MAX_VALUE,原因接下来分析 sqlBuilder.appendLiterals
中它又提出使用 SQLBuilder(官方:lower but much faster API) 来进行批量操作,例如用 sqlbuilder.Insert 和 sqlrepr() 生成 query 后 ) 中执行,类似的 queryAll() 调用相同的数据库方法,只是结果返回 fetchALL(),但是最终结果让我不能仍受,插入100行几乎就像无响应一样,代码如下: from sqlobject.sqlbuilder
if (page.getStartRow() == 0) { sqlBuilder.append(" LIMIT ? "); } else { sqlBuilder.append(" LIMIT ?, ? "); } return sqlBuilder.toString(); } 经过上面的sql重组之后,就可以得到具体分页的list数据了, 返回的也是list数据 sqlBuilder.append(sql); sqlBuilder.append(" ) TMP_PAGE)"); sqlBuilder.append(" WHERE ; return sqlBuilder.toString(); } } 从OracleDialect的实现中,我们看到它与mysql的差异仅在参数设置和获取分页sql时的差别,
进入了OracleParser类中(还有很多其他的Parser,适用于不同的数据库), public String getPageSql(String sql) { StringBuilder sqlBuilder = new StringBuilder(sql.length() + 120); sqlBuilder.append("select * from ( select tmp_page.*, rownum row_id from ( "); sqlBuilder.append(sql); sqlBuilder.append(" ) tmp_page where rownum <= ? ; return sqlBuilder.toString(); } 终于,原来分页的SQL是在这里拼装起来的。
keyword.trim() + '`'; } /** * 输出 */ private void saveData() { StringBuilder sqlBuilder sqlValueBuilder.deleteCharAt(sqlValueBuilder.length() - 1); sqlValueBuilder.append(";"); sqlBuilder.append (sqlHeadBuilder); sqlBuilder.append(sqlValueBuilder); try { fileWriter.write ("\n"); fileWriter.write(String.valueOf(sqlBuilder)); fileWriter.write("\n");
String INSERT = " INSERT "; protected final String INTO = " INTO "; protected StringBuilder sqlBuilder BaseSQLBuilder { public String querySql(Object t) throws Exception { getTableName(t); sqlBuilder.append = value) { sqlBuilder.append(AND).append(fieldStr).append("=").append("'").append(value ).append("'"); } } return sqlBuilder.toString(); } } 执行sql语句 JdbcTemplate
代码实现 介绍一下几个重要的类 (1) 用于构造SQL语句的类SQLBuilder(主要用了Java反射机制) (2) 用于执行SQL语句的类SQLiteDBExecutor (3) 提供给外部使用的 ORM主类LazyDB 3.1 SQLBuilder:SQL语句构建器 该Class的主要作用是,将外部传进来的Object(对象)或者Class(类),通过Java反射机制,构建成SQL语句。 Field数组,找出主键的Field,拼到SQL的字符串里; (3)再次遍历Field数组,过滤掉主键的Field、final、static,拼到SQL的字符串里; 具体代码如下: // SQLBuilder return 数据库游标 Cursor */ public Cursor executeNative() { // 查询表是否存在 String sql = SQLBuilder.buildQueryTableIsExistSql cursor.close(); } } else { return null; } //String sql = SqlBuilder.buildQuerySql
SqlBuilder SqlBuilder是一个非常有用的类,使用它可以灵活地构建SQL语句的条件,一些常用的条件构建方法如下。 条件查询 使用SqlBuilder类构建StatementProvider,然后调用Mapper接口中的方法即可。 username = 'macro' AND STATUS IN ( 0, 1 ) ) ORDER BY create_time DESC; 使用Dynamic SQL对应的Java代码实现如下,使用SqlBuilder ( SELECT admin_id FROM ums_admin_role_relation WHERE role_id = 1 ) 使用Dynamic SQL对应的Java代码实现如下,可以发现SqlBuilder 的条件构造方法isIn中还可以嵌套SqlBuilder的查询。