[翻译] ORMLite document -- How to Use Part (二)
前言
此文档翻译于第一次学习 ORMLite 框架,如果发现当中有什么不对的地方,请指正。若翻译与原文档出现任何的不相符,请以原文档为准。原则上建议学习原英文文档。
----------------------------------------------------------------------------------------------
二、如何使用
2.7 表的创建
ORMLite 提供了一些工具类为您存储在数据库中的类创建 table 和 schema。
2.7.1 TableUtils 类
TableUtils
类提供了大量帮助创建和删除 table,以及提供 schema 声明的静态方法。请参阅 TableUtils Class
- createTable(ConnectionSource, Class)
- createTableIfNotExists(ConnectionSource, Class)
- createTable(ConnectionSource, DatabaseTableConfig)
- createTableIfNotExists(ConnectionSource, DatabaseTableConfig)
- dropTable(ConnectionSource, Class, boolean ignoreErrors)
- dropTable(ConnectionSource, DatabaseTableConfig, boolean ignoreErrors)
- getCreateTableStatements(ConnectionSource, Class)
- clearTable(ConnectionSource, Class)
- clearTable(ConnectionSource, DatabaseTableConfig)
2.7.2 TableCreator Class
TableCreator 这个类虽然是为使用Spring框架设计的,但是在其他的配置方面是很有用的。它配置 ConnectionSource 和被程序使用的 DAO 列表。
如果系统属性ormlite.auto.create.tables设置成true值,他会自动创建和这些DAO相关的表。如果系统属性ormlite.auto.drop.tables设置成true值,它也会自动删除创建的表。这在测试的时候特别有用:你开始使用取得最新schema的测试数据库,但是实际生产过程中你需要手动改变一个具体的schame。你可以在你运行测试脚本的时候设置系统属性,但是在运行实际脚本时要关闭它
List<Dao<?, ?>> daoList = new ArrayList<Dao<?, ?>>();
daoList.add(accountDao);
…
TableCreator creator =
new TableCreator(connectionSource, daoList);
// create the tables if the right system property is set
creator.maybeCreateTables();
…
// later, we may want to drop the tables that were created
creator.maybeDropTables();
2.8 唯一标识
数据库行可以由特定的列定义为标识列的标识。行不需要具有标识列,但很多 DAO 操作 (更新、 删除、 刷新) 要求标识列。这个标识可以由用户提供,或者可以由数据库自动生成。如果你想要查询的 id,删除、 刷新或更新使用 DAO 的特定行,必须存在一个对表的每一行来说唯一值。要将一个字段配置为标识字段,您应该使用一个 (且只有一个) 从 @DatabaseField
以下的三种设置: id
、 generatedId
或 generatedIdSequence。
2.8.1 Id
在我门的示例 Account中,字符串name
字段已经标明id = true
。这意味着 name
为对象的标识字段。存储在数据库中的每个 Account 必须有一个唯一的值为name
字段 — — 你不能有两行"John Smith"这个名字。
public class Account {
@DatabaseField(id = true)
private String name;
…
}
当您使用 DAO 来查找具有特定名称的帐户时,您将使用标识字段在数据库中查找Account
对象:
Account account = accountDao.queryForId("John Smith");
if (account == null) {
// the name "John Smith" does not match any rows
}
注:如果你需要更改一个对象标识字段的值,你必须使用 Dao.updateId()
方法。ORMLite 首先按其旧的 ID 找到对象,然后更新它为新的 ID。请参阅updateId.
2.8.2 generatedId
你可以配置一个 long 或 integer 类型的字段为标识列,这个标识列将被自动数据库字段生成。
public class Order {
@DatabaseField(generatedId = true)
private int id;
…
}
当传递一个 Order 对象到 create 方法,存储到数据库,这个标识字段的值将被数据库返回并且通过 ORMLite 设置给 object。在大多数数据库中,这个值生成的值从1开始,每次+1。
// build our order object without an id
Order order = new Order("Jim Sanders", 12.34);
…
orderDao.create(order);
System.out.println("Order id " + order.getId() +
" was persisted to the database");
// query for the order with an id of 1372
order = orderDao.queryForId(1372);
if (order == null) {
// none of the order rows have an id of 1372
}
在上面的代码示例中,命令构造具有 name 和 amount (例如)。当它被传递给 DAO 的 create
方法时,id 字段未设置。它已保存到数据库后,生成 id 将在 id 字段上被 ORMLite 设值,并且在 create
方法返回的 order 对象上调用 getId()
时将可用。
注:此外可以生成其他特殊字段类型如UUID
。请参阅UUID.
注:您可以使用allowGeneratedIdInsert
字段设置,以允许插入对象到一个表或没有 id 已经设置。请参阅allowGeneratedIdInsert.
2.8.2 generatedIdSequence
某些数据库使用的序列发生器提供生成的 id 值。如果您使用 generatedId = true,
那些数据库序列名称将由 ORMLite 自动生成。如果,你需要设置的名称在现有的 schema 中存在,你可以使用 generatedIdSequence
值的序列的字符串名称。
public class Order {
@DatabaseField(generatedIdSequence = "order_id_seq")
private int id;
…
}
在上面的示例中, id
值自动重新生成但使用名称order_id_seq
的序列。如果您正在使用一个数据库,它不支持序列,这将引发异常。
2.9 DAO 的使用
下面通过使用DAO方法简单完成数据库操作
- 创建并且持久化对象到数据库。
用对象插入一条记录到数据库中。
Account account = new Account(); account.name = "Jim Coakley"; accountDao.create(account);
- 通过 ID 查询
如果对象有通过注解定义的 ID 成员变量,我们可以通过它的 ID 在数据库中查找这个对象。
Account account = accountDao.queryForId(name); if (account == null) { account not found handling … }
- 更新与该对象关联的数据
如果你在内存中改变一个对象的成员变量,你必须调用update把它持久化到数据库。这需要一个 ID 字段
account.password = "_secret"; accountDao.update(account);
- 刷新数据库有改变的对象
如果一些与内存中对象相关的数据库实体发生了改变,你就需要刷新来得到最新的存储对象。这需要一个 ID 字段。
accountDao.refresh(account);
- 从数据库中删除数据
从数据库删除与对象关联的记录。一旦对象从数据库删除,你可以继续使用内存中的对象但是任何的更新或者刷新都很可能失败。这需要一个 ID 字段。
accountDao.delete(account);
- 遍历表中所有记录
DAO也有迭代器,所以你可以简单的执行数据库中所有的记录。
// page through all of the accounts in the database for (Account account : accountDao) { System.out.println(account.getName()); }
注意:你必须遍历迭代器所有的条目来关闭底层的SQL对象。如果你没有通过循环走所有的途径,那么ORMLite不知道关闭底层对象,并且一个到数据库的连接可能泄露,如果更迟一些垃圾回收器才获得它,那么它将被迫关闭,这会在你的代码中产出漏洞。使用下面的try ... finally模板包住迭代器。
例如,下面的for
循环是一个非常坏的模式。for (Account account : accountDao) { if (account.getName().equals("Bob Smith")) { // you can't return, break, or throw from here return account; } }
如果退出循环则会引发异常,因此不应在这些情况下使用
for
循环,这也可能发生。这也是懒加载集合的情况。请参见lazy collection iterator. - 直接使用迭代器
您还可以使用迭代器直接因为for
循环不是最佳。这使您可以使用try ... finally
这是一个很多更好的模式。
CloseableIterator<Account> iterator = accountDao.closeableIterator(); try { while (iterator.hasNext()) { Account account = iterator.next(); System.out.println(account.getName()); } } finally { // close it at the end to close underlying SQL statement iterator.close(); }
- 获得一个包装的迭代器
你也可以使用"wrapped iterable",它允许你在finally中使用close而一直使用循环。
CloseableWrappedIterable<Account> wrappedIterable = accountDao.getWrappedIterable(); try { for (Account account : wrappedIterable) { … } } finally { wrappedIterable.close(); }
2.10 索引字段
ORMLite 为 POJO 中的多个字段的索引提供一些有限的支持。首先,它重点指明任何被标记成 ID 的成员属性被编入索引。被 ID 标记的成员属性不再需要创建额外的索引,如果被指定的话,某些数据库可能会发生错误。
对非主键字段添加索引你需要添加注解 @DatabaseField(index=true), 请参阅 index。这将会在表被创建时创建一个非唯一的索引给成员变量并且如果表被删除那么将删除索引。索引用于帮助优化查询并且在查询媒介中数据量大的表时显著优化了查询时间。
public class Account { @DatabaseField(id = true) private String name; // this indexes the city field so queries on city // will go faster for large tables @DatabaseField(index = true) private String city; … }
本示例在 Account 表上创建索引 account_city_idx
。如果你想要使用一个不同的名称,则可以使用 indexName = "othername",
允许你指定的索引的名称。
如果你经常需要一起查询 city 和 state 在一条 SQL 语句上,这种情况下你可能想要在这两个字段上创建索引。ORMLite 支持多个字段创建索引通过指定相同的 indexName
值为每个您想要在索引的成员属性上。
@DatabaseField(indexName = "account_citystate_idx") private String city; @DatabaseField(indexName = "account_citystate_idx") private String state;
这个示例会为 city 和 state 成员输出创建同一个索引。注意,单独通过 city 查询是没有查询优化的,只有同时在 city 和 state 两个字段做多关键字查询时才会被优化。在某些数据库上,查询 city 和 state 时对每个字段单独建立索引,让数据库同时使用两个索引,可能是更好的选择。对于另一些数据库,推荐在多个成员变量上创建一个索引。你可能需要尝试使用SQL EXPLAIN命令来查明你的数据库是怎么使用你的索引的。
创建一个唯一的索引,uniqueIndex = true 和 uniqueIndexName ="othername" 在 @DatabaseField 注解中都是有效的。这些操作和上面的设置一样,只是创建唯一索引来确保没有任何两条记录的索引有相同的值。
-----------------------------------------------------------------------------
由于本文档篇幅过长,之后的部分请参阅[翻译] ORMLite document -- How to Use Part (三)