从SQLite迁移至Realm:如何打印Realm查询语句?
刚好我之前做过SQLite到Realm的迁移,也纠结过怎么把Realm的链式查询转换成像SQL那样直观的语句打印出来,给你分享两个实用的办法:
方法一:利用Realm原生API获取查询语句
Realm的RealmQuery对象自带了getQueryString()方法,能直接返回当前查询的条件表达式,我们只需要结合实体类名、排序规则等信息,就能拼接出类似SQL的语句。
拿你给出的查询为例,代码实现如下:
// 先构建你的Realm查询 RealmQuery<Patient> query = realm.where(Patient.class) .equalTo("revision", "8") .and() .beginGroup() .like("long_description", "*bone*").or() .like("code", "*bone*") .endGroup() .sort("code"); // 获取Realm原生的查询条件字符串 String realmQueryExpr = query.getQueryString(); // 拼接成SQL风格的语句 String sqlLikeQuery = String.format("SELECT * FROM Patient WHERE %s ORDER BY code", realmQueryExpr); // 打印输出 System.out.println(sqlLikeQuery);
这段代码会输出:
SELECT * FROM Patient WHERE revision = "8" AND (long_description LIKE "bone" OR code LIKE "bone") ORDER BY code
注意:Realm的like查询用*作为通配符,而SQL用%,如果需要完全匹配SQL的格式,你可以手动替换字符串:
String sqlLikeQuery = String.format("SELECT * FROM Patient WHERE %s ORDER BY code", realmQueryExpr.replace("*", "%"));
方法二:自定义工具类生成完美匹配SQL风格的语句
如果原生API返回的格式还是不符合你的预期,或者你想更灵活控制输出格式,可以自己封装一个工具类,在构建Realm查询的同时记录条件,最后生成完全贴合SQL的语句。
比如写一个简单的日志工具类:
public class RealmQuerySqlLogger<T> { private final Class<T> entityClass; private final StringBuilder conditionBuilder = new StringBuilder(); private String sortField; public RealmQuerySqlLogger(Class<T> entityClass) { this.entityClass = entityClass; } // 记录equalTo条件 public RealmQuerySqlLogger<T> equalTo(String field, Object value) { appendCondition(String.format("%s = '%s'", field, value)); return this; } // 记录like条件,自动把Realm的*换成SQL的% public RealmQuerySqlLogger<T> like(String field, String pattern) { String sqlPattern = pattern.replace("*", "%"); appendCondition(String.format("%s LIKE '%s'", field, sqlPattern)); return this; } // 分组开始 public RealmQuerySqlLogger<T> beginGroup() { conditionBuilder.append("("); return this; } // 分组结束 public RealmQuerySqlLogger<T> endGroup() { conditionBuilder.append(")"); return this; } // 逻辑AND public RealmQuerySqlLogger<T> and() { conditionBuilder.append(" AND "); return this; } // 逻辑OR public RealmQuerySqlLogger<T> or() { conditionBuilder.append(" OR "); return this; } // 记录排序字段 public RealmQuerySqlLogger<T> sort(String field) { this.sortField = field; return this; } // 拼接条件的辅助方法 private void appendCondition(String condition) { if (conditionBuilder.length() > 0 && !conditionBuilder.toString().endsWith("(") && !conditionBuilder.toString().endsWith(" AND ") && !conditionBuilder.toString().endsWith(" OR ")) { conditionBuilder.append(" AND "); } conditionBuilder.append(condition); } // 生成SQL风格的查询语句 public String toSqlString() { StringBuilder sql = new StringBuilder(String.format("SELECT * FROM %s", entityClass.getSimpleName())); if (conditionBuilder.length() > 0) { sql.append(" WHERE ").append(conditionBuilder); } if (sortField != null) { sql.append(" ORDER BY ").append(sortField); } return sql.toString(); } }
使用这个工具类的方式也很简单,和构建Realm查询同步进行即可:
// 1. 用工具类记录查询条件 RealmQuerySqlLogger<Patient> queryLogger = new RealmQuerySqlLogger<>(Patient.class) .equalTo("revision", "8") .and() .beginGroup() .like("long_description", "*bone*") .or() .like("code", "*bone*") .endGroup() .sort("code"); // 打印SQL风格语句 System.out.println(queryLogger.toSqlString()); // 2. 正常执行Realm查询 RealmQuery<Patient> query = realm.where(Patient.class) .equalTo("revision", "8") .and() .beginGroup() .like("long_description", "*bone*").or() .like("code", "*bone*") .endGroup() .sort("code"); RealmResults<Patient> results = query.findAll();
这次输出的语句就和你原来的SQL几乎完全一致了:
SELECT * FROM Patient WHERE revision = '8' AND (long_description LIKE '%bone%' OR code LIKE '%bone%') ORDER BY code
小提示
- 对于复杂查询(比如关联查询、聚合函数),原生API的
getQueryString()可能无法完全转换成标准SQL,这时候自定义工具类的灵活性就体现出来了。 - 如果是Kotlin项目,写法类似,Realm的
RealmQuery同样有queryString属性可以直接获取查询表达式。
内容的提问来源于stack exchange,提问作者Mehta
相关产品推荐
相关产品推荐

