实际上,我设法做到了,而无需将整个查询编写为原始查询。这样,我不需要替换我的查询构建器代码(这非常复杂)。为此,我遵循了以下步骤:
(假设我有两个表my_table和my_join_table及其 daos,我想通过my_join_table的列order_column_1对my_table的查询进行排序)
1-加入两个查询构建器并使用QueryBuilder.selectRaw(String... columns)
方法来包括原始表+我想在外部排序中使用的列。例子:
QueryBuilder<MyJoinTable, MyJoinPK> myJoinQueryBuilder = myJoinDao.queryBuilder();
QueryBuilder<MyTable, MyPK> myQueryBuilder = myDao.queryBuilder().join(myJoinQueryBuilder).selectRaw("`my_table`.*", "`my_join_table`.`order_column` as `order_column_1`");
2- 包括我的订单由这样的条款:
myQueryBuilder.orderByRaw("`order_column_1` ASC");
3- 设置所有选择列和 order by 子句后,是时候准备语句了:
String statement = myQueryBuilder.prepare().getStatement();
4- 从 dao 获取表信息: TableInfo tableInfo = ((BaseDaoImpl) myDao).getTableInfo();
5-创建了我的自定义列到对象映射器,它忽略了未知的列名。通过这样做,我们避免了自定义列的映射错误(order_column_1
在这种情况下)。例子:
RawRowMapper<MyTable> mapper = new UnknownColumnIgnoringGenericRowMapper<>(tableInfo);
6-查询表的结果:
GenericRawResults<MyTable> results = activityDao.queryRaw(statement, mapper);
7-最后,将通用原始结果转换为列表:
List<MyTable> myObjects = new ArrayList<>();
for (MyTable myObject : results) {
myObjects.add(myObject);
}
这是我通过修改(只是吞下异常)创建的自定义行映射器,com.j256.ormlite.stmt.RawRowMapperImpl
以避免未知的列映射错误。您可以将其复制并粘贴到您的项目中:
import com.j256.ormlite.dao.RawRowMapper;
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.table.TableInfo;
import java.sql.SQLException;
public class UnknownColumnIgnoringGenericRowMapper<T, ID> implements RawRowMapper<T> {
private final TableInfo<T, ID> tableInfo;
public UnknownColumnIgnoringGenericRowMapper(TableInfo<T, ID> tableInfo) {
this.tableInfo = tableInfo;
}
public T mapRow(String[] columnNames, String[] resultColumns) throws SQLException {
// create our object
T rowObj = tableInfo.createObject();
for (int i = 0; i < columnNames.length; i++) {
// sanity check, prolly will never happen but let's be careful out there
if (i >= resultColumns.length) {
continue;
}
try {
// run through and convert each field
FieldType fieldType = tableInfo.getFieldTypeByColumnName(columnNames[i]);
Object fieldObj = fieldType.convertStringToJavaField(resultColumns[i], i);
// assign it to the row object
fieldType.assignField(rowObj, fieldObj, false, null);
} catch (IllegalArgumentException e) {
// log this or do whatever you want
}
}
return rowObj;
}
}
这很 hacky 并且对于这个操作来说似乎有点矫枉过正,但我绝对需要它,而且这种方法效果很好。