Android数据库ORMlite框架翻译系列(第二章:part 1)

前言

由于第二章是整个文档的核心,内容也很多,所以分次翻译。下一章的内容会继续本章接着翻译。

-------------------------------------------------------------------------------------

 

2 如何使用

这一章进入到更多详细地使用ORMLite的各种功能。

 

2.1 配置你的Class

为了配置你的class使其持久化,你需要做下面几步:

①添加@DatabaseTable 注解到你每个需要持久化的类的顶部。你也可以用@Entity

②添加@DatabaseField 注解到你需要持久化的字段的上面。你也可以使用@Column和其他的。

③为每个class添加一个无参的构造器,并且构造器在包内是可见的。

 

2.1.1 添加ORMLite 注解

自从java5开始,注解是有效的特殊代码标识,它提供meta信息包括类、方法或成员变量。把指定的类和成员变量存入数据库,ORMLite既支持它自己的注解(@DatabaseTable和 @DatabaseField)也支持很多来自javax.persistence包中标准的注解。注解是配置你的class最简单的方式,当然你也可以使用java代码或者Spring xmlSpring是个框架,更多信息google一下)对class进行配置。

ORMLite注解,对每个你想要持久化到SQL数据库的java类你都需要添加@DatabaseTable注解到public class 这一行的正上方。每个被这些注解标记过的class都将持久化到它自己的数据库表中。例如:

@DatabaseTable(tableName = "accounts")

public class Account {

...

 

@DatabaseTable注解可以有个可选的tableName 参数,也就是这个类对于的表名。如果没有特别指出,那么这个类名将默认作为表名。使用示例中的Account的对象都将会作为一条记录持久化到数据库名为account的表中。这将会在DaoManager实例化内部Dao的时候使用到。

除此之外,对于每个class你需要添加@DatabaseField注解到class的成员变量上,这个类是需要持久化到数据库的。每个成员变量都将被作为数据库中记录的一个字段进行持久化。示例:

 

@DatabaseTable(tableName = "accounts")

public class Account {

@DatabaseField(id = true)

private String name;

@DatabaseField(canBeNull = false)

private String password;

...

 

name字段,它是一个字符串并且是数据库中记录的唯一标识(主键)。在上面的示例中,account表的每条记录都有两个字段:

password字段,它也是一个字符串,它不能为null

@DatabaseField注解可以用下面的一些成员:(对常用的字段进行翻译,其他的参考原文)

常用的注解

成员名

数据类型

描述

columnName

String

数据库的列名。如果你没有设置这个成员名,会用标准的形式代替它。

dataType

 

字段的数据类型。通常情况下,数据类型是从java类的成员变量获取的,并不需要进行特殊指出。它相当于是SQL的数据类型。

defaultValue

String

当我们在表中创建新的记录时的一个字段的默认值。默认情况下是没有这个值的。

width

Integer

字段的宽度,主要用于字符串字段。默认是0,意味着采用默认的数据类型和具体的数据库的默认情况。对于字符串以为在255个字符即使有些数据库并不支持。

canBeNull

Boolean

字段是否能被分配null值。默认是true。如果你设置成false,那么你每次在数据库中插入数据是都必须为这个字段提供值。

id

Boolean

这个字段是否是id,默认是false。在一个class中只有一个成变量可以有这个值。id字段是一条记录的唯一标识而且是必需的,只有generatedId和 generatedIdSequence其中之一。

generatedId

Boolean

字段是否自动增加。默认为false。类中的一个成员变量设置了这个值,它告诉数据库每添加一条新记录都自动增加id。当一个有generatedid的对象被创建时使用Dao.create()方法,数据库将为记录生成一个id,它会被返回并且被create方法设置进对象。

generatedIdSequence

String

序列编号的名字,这个值在生成的时候会被使用。和generatedId相似,但是你能够指定使用的序列名称。默认是没有的。一个class中只有一个成员变量可以设置这个值。这仅仅在数据库需要序列生成id时才需要它。如果你选择使用generatedId代替它,那么代码将自动增加序列名。

 

其他注解

foreign

throwIfNull

useGetSet

persisted

unknownEnumName

format

uniqueIndexName

allowGeneratedIdInsert

foreignAutoRefresh

columnDefinition

unique

uniqueIndex

uniqueCombo

indexName

index

uniqueIndexName

version

maxForeignAutoRefreshLevel

foreignColumnName

foreignAutoCreate

 

2.1.2 使用javax.persistence 注解

取代使用ORMLite注解,你可以使用来自javax.persistence包的更多的标准JPA注解。取代@DatabaseTable注解,你可以使用javax.persistence @Entity注解。示例:

@Entity(name = "accounts")

public class Account {

...

 

@Entity注解有个可选的name参数,它用于指定表名。如果没有指定,类名将是默认的表名。

在每个成员变量中取代使用@DatabaseField注解,你可以用javax.persistence注解: @Column, @Id, @GeneratedValue, @OneToOne,@ManyToOne, @JoinColumn, and @Version. 示例:


下面这些javax.persistence注解和字段都支持:

注解

注解属性

描述

@Entity

name

用于关联的数据库表的名字。如果没有设置那么类名将被作为表名。

@Column

name

用作表字段的名字。如果没有设置那么变量名将作为字段名。

length

数据库表字段的长度。可能只有应用在字符串并且只被某些数据库类型支持。默认是255

nullable

设置成true,那么这个字段允许插入null值。

unique

 添加一个约束,它在表中必须是唯一的。

@GeneratedValue

 

用于定义一个自动增长的id值,它只能用于添加到@Id注解。

 

@OneToOne 

 

成员变量使用这些注解后会被认为是外键字段。 ORMLite没有实现多个或一个关系,它也不能使用任何注解成员。它只能使用这些注解的两者之一来表明它是一个外键。

@ManyToOne

 

@JoinColumn

name

设置成员变量的列名(字段名)。

nullable

设置成true,那么这个字段允许插入null值。

@Version

 

使用它将会把short, integer, long,  Date这些类型的成员转化成版本成员。

如果@Column注解在成员变量上用了一个未知的类型,那么它将被认为是序列化类型字段并且这个对象需要实现java.io.Serializable

 

2.1.3 添加无参构造器

在你给class添加了注解字段后,你也需要添加一个无参的包内可见的构造器。当一个对象在查询中被返回时,ORMLite使用java反射机制构造一个对象并且构造器需要被调用。所以你最终的示例拥有注解和构造器的Account类应该像这样:

 

@DatabaseTable(tableName = "accounts")

public class Account {

@DatabaseField(id = true)

private String name;

@DatabaseField(canBeNull = false)

private String password;

...

Account() {

// all persisted classes must define a no-arg constructor

// with at least package visibility

}

...

}

 

2.2 持久化数据类型 

下面这些java类型能够被ORMLite持久化到数据库。数据库具体编码帮助SQL类型和数据库具体持有类型的相互转化。

(具体的类型相互转化在此就不作介绍了,参见原文)。

 

2.3 连接源

注意:关于连接源,android用户应该参见手册中Android详细文档。

为了使用数据库和DAO对象,你需要配置JDBC调用数据源和ORMLite调用连接源。连接源是连接物理SQL数据库的一个工厂。这里是创建简单、单连接的代码示例:

// single connection source example for a database URI

ConnectionSource connectionSource =

new JdbcConnectionSource("jdbc:h2:mem:account");

 

这包中也包括了类JdbcPooledConnectionSource ,它是一个相对简单的连接池的实现。一个数据库连接已经释放而成为关闭,之后向他们添加内部列表他们都会拒绝。只有在没有休眠的可用的连接时,新的连接才需要创建。JdbcPooledConnectionSource也是同步的并且可以用于多线程中。在连接关闭前它可以设置空闲连接的最大数和存活的最长时间。

// pooled connection source

JdbcPooledConnectionSource connectionSource =

new JdbcPooledConnectionSource("jdbc:h2:mem:account");

// only keep the connections open for 5 minutes

connectionSource.setMaxConnectionAgeMillis(5 * 60 * 1000);

 


JdbcPooledConnectionSource也有一个一直存活的线程,它偶尔ping一下池中空闲的每个连接,目的是为了确认他们是有效的,关闭的那个就不再有效。在你从池中取得连接之前你也可以测试连接是否有效。

// change the check-every milliseconds from 30 seconds to 60

connectionSource.setCheckConnectionsEveryMillis(60 * 1000);

// for extra protection, enable the testing of connections

// right before they are handed to the user

connectionSource.setTestBeforeGet(true);

 


有很多其他额外的数据,他们能够被使用,包括很多更强大甚至高性能的池连接管理器。你可以用你自己直接封装的DataSourceConnectionSource类来例举说明。

// basic Apache data source

BasicDataSource dataSource = new BasicDataSource();

String databaseUrl = "jdbc:h2:mem:account";

dataSource.setUrl(databaseUrl);

// we wrap it in the DataSourceConnectionSource

ConnectionSource connectionSource =

new DataSourceConnectionSource(dataSource, databaseUrl);

 


当你用ConnectionSource时,你想调用close()方法来关闭一些底层的连接。推荐像下面这样的模式。

JdbcConnectionSource connectionSource =

new JdbcPooledConnectionSource("jdbc:h2:mem:account");

try {

// work with the data-source and DAOs

...

} finally {

connectionSource.close();

}

 


很不幸,DataSource接口没有关闭方法,所以你使用DataSourceConnectionSource你必须关闭底层数据源,通过操作DataSourceConnectionSource上的close()方法。

 

2.4 配置DAOs

一旦在你的类中有注解并且定义了你的ConnectionSource,你就需要创建一个DAOData Access Object),它是一个拥有数据库操作句柄的单一持久化类。每个DAO都有两个泛型参数:①我们用DAO持久化的类,②id字段,它用于确定数据库具体的记录。如果你的类没有ID字段,你可以放入Object或者Void作为第二个参数。例如,在上面的Account类,成员变量nameID字段,所以ID类是String

创建DAO最简单的方式是使用DaoManager类的静态方法createDao。示例:

Dao<Account, String> accountDao =

DaoManager.createDao(connectionSource, Account.class);

Dao<Order, Integer> orderDao =

DaoManager.createDao(connectionSource, Order.class);

 


注意:你需要使用DaoManager.createDao()方法创建你自己的DAO类,所以如果内置ORMLite功能是需要他们,他们可以被再次利用并且不能再次生成。创建DAO会有昂贵的操作代价并且很多设备有资源限制(比如移动设备应用),尽可能重复使用DAO 

如果你想更好的类层次的机构或者你需要添加附加的方法套你的DAOs中,你应该考虑定义一个接口,它继承自Dao接口。这个接口不是必需的,但是他说一种好的模式,这样你的代码在关联JDBC持久化的时候会更少。接下来是一个相当于本手册前面章节Account类的DAO接口的示例:

/** Account DAO which has a String id (Account.name) */

public interface AccountDao extends Dao<Account, String> {

// empty wrapper, you can add additional DAO methods here

}

 

然后在实现中,你需要扩展BaseDaoImpl基类。这里是个实现你的DAO接口的示例。

/** JDBC implementation of the AccountDao interface. */

public class AccountDaoImpl extends BaseDaoImpl<Account, String>

implements AccountDao {

public AccountDaoImpl(ConnectionSource connectionSource)

throws SQLException {

super(connectionSource, Account.class);

}

}

 


那就是你需要定义你的DAO类。如果有特殊的操作需要并且Dao基类没有提供的方法,你可以自由添加更多方法到你的DAO接口和添加到你的实现中。

注意:如果你正在使用一个定制的DAO,然后确保添加daoClass参数到你自己定制的DAO类的@DatabaseTable注解。这会被DaoManager用于内部实例化DAO

 

2.5 支持的数据库

ORMLite支持下面的数据库。这些数据库中的某些数据库有具体需要遵守的文档。(下面给出支持的数据库,具体文档参见官方文档)

支持的数据库

MySQL

H2

Android SQLite

HSQLDB

Netezza

DB2

Postgres

SQLite

Microsoft SQL Server

Derby

ODBC

Oracle

 

2.6 整合

这样你有一个注解对象被持久化,添加一个无参构造器,创建你的ConnectionSource并且定义你的DAO类。你已经开始持久化和查询你的数据库对象了。你需要下载并且添加H2 jar文件到你的classPath中,如果你想让这个示例跑起来的话。下面是整合的代码:

// h2 by default but change to match your database

String databaseUrl = "jdbc:h2:mem:account";

JdbcConnectionSource connectionSource =

new JdbcConnectionSource(databaseUrl);

// instantiate the dao with the connection source

AccountDaoImpl accountDao = new AccountDaoImpl(connectionSource);

// if you need to create the 'accounts' table make this call

TableUtils.createTable(connectionSource, Account.class);

// create an instance of Account

Account account = new Account("Jim Coakley");

// persist the account object to the database

accountDao.create(account);

...

// destroy the data source which should close underlying connections

connectionSource.destroy();

 


PS: 第二章还在翻译中... 文中有不妥之处希望读者提出,转载请注明出处。

 

posted on 2012-08-02 13:28  vanezkw  阅读(13313)  评论(0编辑  收藏  举报

导航