SQL语句使用包装类

在Android SQL,SQL编写是一件不好玩的事,所以为了简单易用,该库提供了一套对SQLite声明的分装,试图使java代码尽可能看上去就像SQLite。

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

例

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

2. SELECT * FROM Ant where type = 'worker' AND isMale = 0;

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

2. String[] args = new String[2];
3. args[0] = "worker";
4. args[1] = "0";
5. Cursor cursor = db.rawQuery("SELECT * FROM Ant where type = ? AND isMale = ?", args);
6. final List<Ant> ants = new ArrayList<Ant>();
7. Ant ant;

9. if (cursor.moveToFirst()) {
10. do {
11. // get each column and then set it on each
12. ant = new Ant();
13. ant.setId(cursor.getLong(cursor.getColumnIndex("id")));
14. ant.setType(cursor.getString(cursor.getColumnIndex("type")));
15. ant.setIsMale(cursor.getInt(cursor.getColumnIndex("isMale") == 1);
16. ant.setQueenId(cursor.getLong(cursor.getColumnIndex("queen_id")));
17. ants.add(ant);
18. }
19. while (cursor.moveToNext());
20. }

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

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

  1. 我们添加或删除列的时候呢?
  2. 在其他表写这样的查询是否每次都要重复写这些代码?或者类似的查询页要重复写这些代码?

总之,我们希望我们的代码是可维护,简短,复用性高,并且仍然表现究竟正在发生的事情。在这个库中,这个查询变得非常简单:

2. // main thread retrieval
3. List<Ant> devices = SQLite.select().from(Ant.class)
4. .where(Ant_Table.type.eq("worker"))
5. .and(Ant_Table.isMale.eq(false)).queryList();

7. // Async Transaction Queue Retrieval (Recommended for large queries)
8. SQLite.select()
9. .from(DeviceObject.class)
10. .where(Ant_Table.type.eq("worker"))
11. .and(Ant_Table.isMale.eq(false))
12. .async().queryList(transactionListener);

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

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

SELECT语句和检索方法

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

  1. 普通的在主线程中 Select
  2. 用TransactionManager 运行一个 Transaction (建议用于大型查询).
2. // 查询一个List
3. SQLite.select().from(SomeTable.class).queryList();
4. SQLite.select().from(SomeTable.class).where(conditions).queryList();

6. //查询单个 Model
7. SQLite.select().from(SomeTable.class).querySingle();
8. SQLite.select().from(SomeTable.class).where(conditions).querySingle();

10. // 从一个表中查询一个list或游标(cursor)
11. SQLite.select().from(SomeTable.class).where(conditions).queryTableList();
12. SQLite.select().from(SomeTable.class).where(conditions).queryCursorList();

14. // 在ModelContainer查询!
15. SQLite.select().from(SomeTable.class).where(conditions).queryModelContainer(new MapModelContainer<>(SomeTable.class));

17. // 查询 methods
18. SQLite.select().distinct().from(table).queryList();
19. SQLite.select().from(table).queryList();
20. SQLite.select(Method.avg(SomeTable_Table.salary))
21. .from(SomeTable.class).queryList();
22. SQLite.select(Method.max(SomeTable_Table.salary))
23. .from(SomeTable.class).queryList();

25. // Transact a query on the DBTransactionQueue
26. TransactionManager.getInstance().addTransaction(
27. new SelectListTransaction<>(new Select().from(SomeTable.class).where(conditions),
28. new TransactionListenerAdapter<List<SomeTable>>() {
29. @Override
30. public void onResultReceived(List<SomeTable> someObjectList) {
31. // retrieved here
32. });

34. // Selects Count of Rows for the SELECT statment
35. long count = SQLite.selectCountOf()
36. .where(conditions).count();

Order By

2. // true for 'ASC', false for 'DESC'
3. SQLite.select()
4. .from(table)
5. .where()
6. .orderBy(Customer_Table.customer_id, true)
7. .queryList();

9. SQLite.select()
10. .from(table)
11. .where()
12. .orderBy(Customer_Table.customer_id, true)
13. .orderBy(Customer_Table.name, false)
14. .queryList();

Group By

1. SQLite.select()
2. .from(table)
3. .groupBy(Customer_Table.customer_id, Customer_Table.customer_name)
4. .queryList();

HAVING

1. SQLite.select()
2. .from(table)
3. .groupBy(Customer_Table.customer_id, Customer_Table.customer_name))
4. .having(Customer_Table.customer_id.greaterThan(2))
5. .queryList();

LIMIT + OFFSET

1. SQLite.select()
2. .from(table)
3. .limit(3)
4. .offset(2)
5. .queryList();

UPDATE语句

这里有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.

使用本地SQL:

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

使用DBFlow:

2. // Native SQL wrapper
3. Where<Ant> update = SQLite.update(Ant.class)
4. .set(Ant_Table.type.eq("other"))
5. .where(Ant_Table.type.is("worker"))
6. .and(Ant_Table.isMale.is(true));
7. update.queryClose();

9. // TransactionManager (more methods similar to this one)
10. TransactionManager.getInstance().addTransaction(new QueryTransaction(DBTransactionInfo.create(BaseTransaction.PRIORITY_UI), update);

DELETE语句

2. // Delete a whole table
3. Delete.table(MyTable.class, conditions);

5. // Delete multiple instantly
6. Delete.tables(MyTable1.class, MyTable2.class);

8. // Delete using query
9. SQLite.delete(MyTable.class)
10. .where(DeviceObject_Table.carrier.is("T-MOBILE"))
11. .and(DeviceObject_Table.device.is("Samsung-Galaxy-S5"))
12. .query();

JOIN声明

作为参考, (JOIN examples).

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() 方法会在前面加上 NameAlias 或 Table 别名到 IProperty查询, 方便连接查询:

1. SELECT EMP_ID, NAME, DEPT FROM COMPANY LEFT OUTER JOIN DEPARTMENT
2. ON COMPANY.ID = DEPARTMENT.EMP_ID

在 DBFlow:

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()))
5. .queryList();