【问题标题】:ORMLite JOINs, or rawQuery auto mappingORMLite JOIN 或 rawQuery 自动映射
【发布时间】:2012-08-16 12:52:24
【问题描述】:

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

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

【问题讨论】:

  • 仅供参考丹尼尔。 ORMLite 4.22 刚刚发布,支持简单的 JOIN 查询。
  • 我之前的 ORMLite 4.23 不支持 JOIN 查询。查看发布日期和评论的时间戳,我相信您的意思是说 ORMLite 4.26,发布于 2012 年 9 月 26 日,是第一个支持简单 JOIN 查询的版本。我刚更新到4.45,肯定有JOIN。

标签: java android orm ormlite


【解决方案1】:

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

ORMLite 支持simple JOIN queries。您也可以使用raw-queries 来完成此操作。

您可以使用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]));
        }
    });

【讨论】:

  • 谢谢@Gray。我找到了所有自定义行映射器的东西,但只是希望它自动映射到我已经定义的对象。 QueryBuilder JOIN 选项将是我的愿望清单上的下一个选项!关于何时/是否会到来的任何消息?
  • 想在 ormlite-dev 上启动线程?我准备写了。更难的是使用连接来水合子对象。但是启动线程,我会回复:groups.google.com/forum/?fromgroups#!forum/ormlite-dev
  • INNER 和 LEFT JOIN 功能是在 ORMLite 4.42 版而不是 4.22 版中引入的 ormlite.com/changelog.txt
  • 哎呀。修正了错字@MarcoMatarazzi。谢谢。
【解决方案2】:

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

// 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();

关键是使用getRawRowMapper() 从对象Dao 中提取行映射器,它将为您处理映射。我希望这对找到它的人有所帮助。

我仍然希望能够在 QueryBuilder 中进行连接,但在得到支持之前,我认为这是下一个最好的事情。

【讨论】:

    【解决方案3】:

    原始查询自动映射

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

    这是执行查询自动映射的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;
        }
    }
    }
    

    这里是用法

    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()
    

    如果查询列名和@DatabaseField(columnName 相同,这将返回带有映射结果行的List&lt;Model&gt; 到模型

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-10
      • 2011-02-02
      • 1970-01-01
      相关资源
      最近更新 更多