3

我正在尝试加入两个表并获取两个表中的所有列,我这样做了:

QueryBuilder<A, Integer> aQb = aDao.queryBuilder();
QueryBuilder<B, Integer> bQb = bDao.queryBuilder();
aQb.join(bQb).prepare();

这相当于:

SELECT 'A'.* FROM A INNER JOIN B WHERE A.id = B.id;

但我想要:

SELECT * FROM A INNER JOIN B WHERE A.id = B.id;

另一个问题是在按 B 的字段排序时,例如:

aQb.orderBy(B.COLUMN, true);

我收到一条错误消息,提示“没有表列 B”。

4

2 回答 2

3

当您使用 时QueryBuilder,它期望返回B对象。它们不能包含Ain 中的所有字段B。如果这就是您的意思,它不会充实外国子领域。该功能尚未跨越ORMLite的lite障碍。

也不支持在连接表上排序。您当然可以添加,bQb.orderBy(B.COLUMN, true)但我认为这不会满足您的要求。

您当然可以为此使用原始查询,尽管它不是最佳的。

于 2013-01-04T23:52:58.070 回答
1

实际上,我设法做到了,而无需将整个查询编写为原始查询。这样,我不需要替换我的查询构建器代码(这非常复杂)。为此,我遵循了以下步骤:

(假设我有两个表my_tablemy_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 并且对于这个操作来说似乎有点矫枉过正,但我​​绝对需要它,而且这种方法效果很好。

于 2015-07-10T16:16:33.947 回答