java ORMLite JOIN 或 rawQuery 自动映射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11987552/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 07:10:29  来源:igfitidea点击:

ORMLite JOINs, or rawQuery auto mapping

javaandroidormormlite

提问by DanO

I am looking for a way to do a query that requires a JOIN. Is there any way to do this in a prepared statement, or is the rawQuerythe only option that I have. If rawQueryis the only option, then is there some way to automatically map the returned objects to the objects of the Dao being implemented.

我正在寻找一种方法来执行需要 JOIN 的查询。有没有办法在准备好的声明中做到这一点,或者是rawQuery我唯一的选择。如果rawQuery是唯一的选择,那么是否有某种方法可以将返回的对象自动映射到正在实现的 Dao 的对象。

I've dug through the documents and examples but cannot find anything that will allow me to map the raw database result to an ORM object class.

我已经翻阅了文档和示例,但找不到任何可以将原始数据库结果映射到 ORM 对象类的内容。

回答by Gray

I am looking for a way to do a query that requires a JOIN.

我正在寻找一种方法来执行需要 JOIN 的查询。

ORMLite supports simple JOIN queries. You can also use raw-queriesto accomplish this.

ORMLite 支持简单的 JOIN 查询。您还可以使用原始查询来完成此操作。

You can use the Dao.getRawRowMapper()to map the queries as you found or you can create a custom mapper. The documentation has the following sample code which shows how to map the String[]into your object:

您可以使用Dao.getRawRowMapper()来映射找到的查询,也可以创建自定义映射器。该文档包含以下示例代码,显示了如何将 映射String[]到您的对象中:

GenericRawResults<Foo> rawResults =
  orderDao.queryRaw(
    "select account_id,sum(amount) from orders group by account_id",
    new RawRowMapper<Foo>() {
            public Foo mapRow(String[] columnNames,
              String[] resultColumns) {
                return new Foo(Long.parseLong(resultColumns[0]),
                    Integer.parseInt(resultColumns[1]));
        }
    });

回答by DanO

I've found a way to auto map a result set to a model object.

我找到了一种将结果集自动映射到模型对象的方法。

// return the orders with the sum of their amounts per account
GenericRawResults<Order> rawResults = 
    orderDao.queryRaw(query, orderDao.getRawRowMapper(), param1)

// page through the results
for (Order order : rawResults) {
  System.out.println("Account-id " + order.accountId + " has "
    + order.totalOrders + " total orders");
}

rawResults.close();

The key is to pull the row mapper from your object Daousing getRawRowMapper(), which will handle the mapping for you. I hope this helps anyone who finds it.

关键是要拉从对象的行映射器Dao使用getRawRowMapper(),将处理您的映射。我希望这可以帮助任何找到它的人。

I still would love the ability to do joins within the QueryBuilderbut until that is supported, this is the next best thing in my opinion.

我仍然喜欢在 内进行连接的能力,QueryBuilder但在支持之前,这是我认为下一个最好的事情。

回答by Roman Nazarevych

Raw query auto mapping

原始查询自动映射

I had problem of mapping fields from custom SELECT which return columns that are not present in any table model. So I made custom RawRowMapperwhich can map fields from custom query to custom model. This is useful when you have query which has fields that doesn't corresponds to any table maping model.

我有从自定义 SELECT 映射字段的问题,这些字段返回任何表模型中不存在的列。所以我做了自定义RawRowMapper,它可以将字段从自定义查询映射到自定义模型。当您的查询具有不对应于任何表映射模型的字段时,这很有用。

This is RowMapperwhich performs query auto mapping:

这是执行查询自动映射的RowMapper

public class GenericRowMapper<T> implements RawRowMapper<T> {

private Class<T> entityClass;
private Set<Field> fields = new HashSet<>();
private Map<String, Field> colNameFieldMap = new HashMap<>();

public GenericRowMapper(Class<T> entityClass) {
    this.dbType = dbType;
    this.entityClass = entityClass;
    Class cl = entityClass;
    do {
        for (Field field : cl.getDeclaredFields()) {
            if (field.isAnnotationPresent(DatabaseField.class)) {
                DatabaseField an = field.getAnnotation(DatabaseField.class);
                fields.add(field);
                colNameFieldMap.put(an.columnName(), field);
            }
        }
        cl = cl.getSuperclass();
    } while (cl != Object.class);
}

@Override
public T mapRow(String[] columnNames, String[] resultColumns) throws SQLException {
    try {
        T entity = entityClass.newInstance();
        for (int i = 0; i < columnNames.length; i++) {
            Field f = colNameFieldMap.get(columnNames[i]);
            boolean accessible = f.isAccessible();
            f.setAccessible(true);
            f.set(entity, stringToJavaObject(f.getType(), resultColumns[i]));
            f.setAccessible(accessible);
        }
        return entity;
    } catch (InstantiationException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

public Object stringToJavaObject(Class cl, String result) {
    if (result == null){
        return null;
    }else if (cl == Integer.class || int.class == cl) {
        return Integer.parseInt(result);
    } else if (cl == Float.class || float.class == cl) {
        return Float.parseFloat(result);
    } else if (cl == Double.class || double.class == cl) {
        return Double.parseDouble(result);
    } else if (cl == Boolean.class || cl == boolean.class) {
        try{
            return Integer.valueOf(result) > 0;   
        }catch (NumberFormatException e){
            return Boolean.parseBoolean(result); 
        }
    } else if (cl == Date.class) {
        DateLongType lType = DateLongType.getSingleton();
        DateStringType sType = DateStringType.getSingleton();
        try {
            return lType.resultStringToJava(null, result, -1);
        } catch (NumberFormatException e) {
            try {
                return sType.resultStringToJava(null, result, -1);
            } catch (SQLException e2) {
                throw new RuntimeException(e);
            }
        }
    } else {
        return result;
    }
}
}

And here is the usage:

这是用法

class Model{
   @DatabaseField(columnName = "account_id")
   String accId;
   @DatabaseField(columnName = "amount")
   int amount;
}

String sql = "select account_id,sum(amount) amount from orders group by account_id"
return queryRaw(sql,new GenericRowMapper<>(Model.class)).getResults()

This will return List<Model>with mapped result rows to Model if query column names and @DatabaseField(columnNameare the same

List<Model>如果查询列名称@DatabaseField(columnName相同,这将返回映射结果行到模型