SQL语句使用包装类

    在第一部分,我描述如何使用包装类彻底简化代码编写。

    例如,我们要在找到所有类型为“工人”,并为女性的蚂蚁。编写SQL语句是很容易的:

    我们想用Android的代码来写这一点,SQL数据转换成有用信息:

    1. String[] args = new String[2];
    2. args[0] = "worker";
    3. args[1] = "0";
    4. Cursor cursor = db.rawQuery("SELECT * FROM Ant where type = ? AND isMale = ?", args);
    5. final List<Ant> ants = new ArrayList<Ant>();
    6. Ant ant;
    7. if (cursor.moveToFirst()) {
    8. do {
    9. // get each column and then set it on each
    10. ant = new Ant();
    11. ant.setId(cursor.getLong(cursor.getColumnIndex("id")));
    12. ant.setType(cursor.getString(cursor.getColumnIndex("type")));
    13. ant.setIsMale(cursor.getInt(cursor.getColumnIndex("isMale") == 1);
    14. ant.setQueenId(cursor.getLong(cursor.getColumnIndex("queen_id")));
    15. ants.add(ant);
    16. }
    17. while (cursor.moveToNext());
    18. }

    这么简短而亲切的简单的查询,但我们为什么要继续写这些语句?

    如果这样写会发生什么呢:

    1. 我们添加或删除列的时候呢?
    2. 在其他表写这样的查询是否每次都要重复写这些代码?或者类似的查询页要重复写这些代码?
    1. // main thread retrieval
    2. List<Ant> devices = SQLite.select().from(Ant.class)
    3. .where(Ant_Table.type.eq("worker"))
    4. .and(Ant_Table.isMale.eq(false)).queryList();
    5. // Async Transaction Queue Retrieval (Recommended for large queries)
    6. SQLite.select()
    7. .from(DeviceObject.class)
    8. .where(Ant_Table.type.eq("worker"))
    9. .and(Ant_Table.isMale.eq(false))
    10. .async().queryList(transactionListener);

    有许多操作在DBFlow得到支持:

    1. SELECT
    2. UPDATE
    3. INSERT
    4. JOIN

    一个SELECT语句从数据库中检索数据。我们通过检索数据

    1. 普通的在主线程中 Select
    2. TransactionManager 运行一个 Transaction (建议用于大型查询).
    1. // 查询一个List
    2. SQLite.select().from(SomeTable.class).queryList();
    3. SQLite.select().from(SomeTable.class).where(conditions).queryList();
    4. //查询单个 Model
    5. SQLite.select().from(SomeTable.class).querySingle();
    6. SQLite.select().from(SomeTable.class).where(conditions).querySingle();
    7. // 从一个表中查询一个list或游标(cursor)
    8. SQLite.select().from(SomeTable.class).where(conditions).queryTableList();
    9. SQLite.select().from(SomeTable.class).where(conditions).queryCursorList();
    10. // 在ModelContainer查询!
    11. SQLite.select().from(SomeTable.class).where(conditions).queryModelContainer(new MapModelContainer<>(SomeTable.class));
    12. // 查询 methods
    13. SQLite.select().distinct().from(table).queryList();
    14. SQLite.select().from(table).queryList();
    15. SQLite.select(Method.avg(SomeTable_Table.salary))
    16. .from(SomeTable.class).queryList();
    17. SQLite.select(Method.max(SomeTable_Table.salary))
    18. .from(SomeTable.class).queryList();
    19. // Transact a query on the DBTransactionQueue
    20. TransactionManager.getInstance().addTransaction(
    21. new SelectListTransaction<>(new Select().from(SomeTable.class).where(conditions),
    22. new TransactionListenerAdapter<List<SomeTable>>() {
    23. @Override
    24. public void onResultReceived(List<SomeTable> someObjectList) {
    25. // retrieved here
    26. });
    27. // Selects Count of Rows for the SELECT statment
    28. long count = SQLite.selectCountOf()
    29. .where(conditions).count();
    1. // true for 'ASC', false for 'DESC'
    2. SQLite.select()
    3. .from(table)
    4. .where()
    5. .orderBy(Customer_Table.customer_id, true)
    6. .queryList();
    7. SQLite.select()
    8. .from(table)
    9. .where()
    10. .orderBy(Customer_Table.customer_id, true)
    11. .orderBy(Customer_Table.name, false)
    12. .queryList();
    1. SQLite.select()
    2. .from(table)
    3. .groupBy(Customer_Table.customer_id, Customer_Table.customer_name))
    4. .queryList();
    1. SQLite.select()
    2. .from(table)
    3. .limit(3)
    4. .offset(2)
    5. .queryList();

    这里有2中更耐心数据库的方法:

    1. 调用 SQLite.update()或者使用 Update
    2. 运行 事务 使用 事务管理器 (推荐线程安全的,但是看到的变化是异步)。

    在本节中,我们将从数据库描述批量更新数据

    在我们对前面蚂蚁的例子中,我们要改变我们目前所有的男性“worker”蚂蚁为“other”蚂蚁,因为他们偷懒不工作了。
    From our earlier example on ants, we want to change all of our current male “worker” ants into “other” ants because they became lazy and do not work anymore.

    1. UPDATE Ant SET type = 'other' WHERE male = 1 AND type = 'worker';

    使用DBFlow:

    1. // Native SQL wrapper
    2. Where<Ant> update = SQLite.update(Ant.class)
    3. .set(Ant_Table.type.eq("other"))
    4. .where(Ant_Table.type.is("worker"))
    5. .and(Ant_Table.isMale.is(true));
    6. update.queryClose();
    7. // TransactionManager (more methods similar to this one)
    8. TransactionManager.getInstance().addTransaction(new QueryTransaction(DBTransactionInfo.create(BaseTransaction.PRIORITY_UI), update);

    作为参考, ().

    JOIN 语句能很好地结合很多一对多的关系。
    如果查询返回非表字段,不能映射到现有的对象,
    If your query returns non-table fields and cannot map to an existing object,
    请参阅有关 查询模式

    例如,我们有一个表名为客户,另一个名为预订

    1. SELECT FROM `Customer` AS `C` INNER JOIN `Reservations` AS `R` ON `C`.`customerId`=`R`.`customerId`
    1. // use the different QueryModel (instead of Table) if the result cannot be applied to existing Model classes.
    2. List<CustomTable> customers = new Select()
    3. .from(Customer.class).as("C")
    4. .join(Reservations.class, JoinType.INNER).as("R")
    5. .on(Customer_Table.customerId
    6. .withTable(new NameAlias("C"))
    7. .eq(Reservations_Table.customerId.withTable("R"))
    8. .queryCustomList(CustomTable.class);

    IProperty.withTable() 方法会在前面加上 NameAliasTable 别名到 IProperty查询, 方便连接查询:

    1. SELECT EMP_ID, NAME, DEPT FROM COMPANY LEFT OUTER JOIN DEPARTMENT
    2. ON COMPANY.ID = DEPARTMENT.EMP_ID
    1. SQLite.select(Company_Table.EMP_ID, Company_Table.DEPT)
    2. .from(Company.class)
    3. .leftOuterJoin(Department.class)
    4. .on(Company_Table.ID.withTable().eq(Department_Table.EMP_ID.withTable()))