接着上一篇,下面是第三章的翻译整理,理解错误的地方还请批评指正。
原文档:http://ormlite.com/javadoc/ormlite-core/doc-files/ormlite_3.html#Statement-Builder
尊重原创,转载请说明出处,谢谢! http://blog.csdn.net/oyangyujun
第三章、 自定义查询构造器
3.1 查询构造器基础
下面是使用查询构造器创建自定义查询语句的基本步骤。首先,以java常量的形式为属性设置列名,便于使用它
们进行查询。
@DatabaseTable(tableName = "accounts")
public class Account {
public static final String PASSWORD_FIELD_NAME = "password";
…
@DatabaseField(canBeNull = false, columnName = PASSWORD_FIELD_NAME)
private String password;
…
这样就允许我们使用password属性构建查询,而不需要在后面的查询中重命名属性,及时属性名,和列名一样也
应该这样做。
// get our query builder from the DAO
QueryBuilder<Account, String> queryBuilder = accountDao.queryBuilder();
// the 'password' field must be equal to "qwerty"
queryBuilder.where().eq(Account.PASSWORD_FIELD_NAME, "qwerty");
// prepare our sql statement
PreparedQuery<Account> preparedQuery = queryBuilder.prepare();
// query for all accounts that have "qwerty" as a password
List<Account> accountList = accountDao.query(preparedQuery);
如上面的代码,你可以通过Dao.queryBuilder()方法获得一个QueryBuilder对象,然后调用这个对象的方法,调
用queryBuilder.prepare()函数获得一个PrepareQuery对象,然后,将这个PrepareQuery方法传递到DAO的查询或者
遍历方法中。
简化操作,可以在Where对象中调用prepare()方法,如下所示:
// query for all accounts that have that password
List<Account> accountList = accountDao.query(
accountDao.queryBuilder().where()
.eq(Account.PASSWORD_FIELD_NAME, "qwerty")
.prepare());
也可以使用另外一种简化方法,通过QueryBuilder或者Where对象调用query()方法或者iterator()方法。如下:
// query for all accounts that have that password
List<Account> accountList =
accountDao.queryBuilder().where()
.eq(Account.PASSWORD_FIELD_NAME, "qwerty")
.query();
3.2 构建查询语句
下面是一些不相同的构建查询语句的方式。QueryBuilder类已经针对特殊使用和强大的用户进行了内部封装。
QueryBuilder<Account, String> queryBuilder =
accountDao.queryBuilder();
// get the WHERE object to build our query
Where<Account, String> where = queryBuilder.where();
// the name field must be equal to "foo"
where.eq(Account.NAME_FIELD_NAME, "foo");
// and
where.and();
// the password field must be equal to "_secret"
where.eq(Account.PASSWORD_FIELD_NAME, "_secret");
PreparedQuery<Account> preparedQuery = queryBuilder.prepare();
上面的语句会生成下面这样的sql语句
SELECT * FROM account
WHERE (name = 'foo' AND password = '_secret')
如果你喜欢使用方法链进行操作,则上面的语句也可以这样写:
queryBuilder.where()
.eq(Account.NAME_FIELD_NAME, "foo")
.and()
.eq(Account.PASSWORD_FIELD_NAME, "_secret");
如果你喜欢使用括号将比较语句组合在一起,也可以这样用:
Where<Account, String> where = queryBuilder.where();
where.and(where.eq(Account.NAME_FIELD_NAME, "foo"),
where.eq(Account.PASSWORD_FIELD_NAME, "_secret"));
上面的三种调用方式会生成相同的sql语句。对于混合mixANDs和ORs的复杂查询而言,最后一种格式必须正确组装
,如下面这个查询:
Where<Account, String> where = queryBuilder.where();
where.or(
where.and(
where.eq(Account.NAME_FIELD_NAME, "foo"),
where.eq(Account.PASSWORD_FIELD_NAME, "_secret")
),
where.and(
where.eq(Account.NAME_FIELD_NAME, "bar"),
where.eq(Account.PASSWORD_FIELD_NAME, "qwerty")
)
);
这个语句会长生下面这样的sql语句:
SELECT * FROM account
WHERE ((name = 'foo' AND password = '_secret')
OR (name = 'bar' AND password = 'qwerty'))
查询语句也允许指定需要查询返回的列,指定ORDER BY和GROUP BY属性,以及各种各样的sql特点,比如(LIKE,IN,>,>=,<, <=,<>, IS NULL, DISTINCT,...),具体细节查看Where Capabilities这节。也可以查看good SQL reference site中关于QueryBuilder和Where语句的java文档介绍。
3.3 构建更新和删除语句
DAO对象也可以用于构建自定义的UPDATE和DELETE语句,UPDATE语句用于改变满足Where条件的数据行中特定的属
性的值,或者,如果没有指定where的话,用于更改所有数据行的属性值。delete语句用于删除满足条件的数据行,
如果没有条件限制,则用于删除所有数据。
例如,如果你想要更新全部Account中passwords为null的值为“none”,可以使用下面的语句。
UpdateBuilder<Account, String> updateBuilder =
accountDao.updateBuilder();
// update the password to be "none"
updateBuilder.updateColumnValue("password", "none");
// only update the rows where password is null
updateBuilder.where().isNull(Account.PASSWORD_FIELD_NAME);
updateBuilder.update();
通过update语句,也可以指定表达式更新
// update hasDog boolean to true if dogC > 0
updateBuilder.updateColumnExpression("hasDog", "dogC > 0");
为了便于构造你的表达式,可以使用UpdateBuilder的escape方法escapeColumnName和escapeValue值,这个两个
方法可以携带一个String或者StringBuffer,这样可以避免列名和关键字冲突。
如果你想删除Account表中password为null的一行,可以使用下面的语句完成。
DeleteBuilder<Account, String> deleteBuilder = accountDao.deleteBuilder();
// only delete the rows where password is null
deleteBuilder.where().isNull(Account.PASSWORD_FIELD_NAME);
deleteBuilder.delete();
3.4 Query功能
下面是关于QueryBuilder各种查询调用的详情。可以查看QueryBuilder类的最新JavaDoc文档获取更多信息。大
多数的方法都是返回QueryBuilder对象,以便使用方法链。
具体细节参考 tutorial of SQL commands.中的详情。
主要方法包括:
distinct()
groupBy(String columnName)
groupByRaw(String sql)
having(String sql)
join(QueryBuilder joinedQueryBuilder)
leftJoin(QueryBuilder joinedQueryBuilder)
limit(Integer maxRows)
offset(Integer startRow)
orderBy(String columnName, boolean ascending)
orderByRaw(String sql)
prepare()
selectColumns(String... columns)
selectColumns(Iterable<String> columns)
selectRaw(String... columns)
where()
query()
queryForFirst()
queryRawFirst()
iterator()
reset()
3.5 Where功能
下面是关于查询功能的详解,更多细节参考tutorial of SQL commands.
主要方法包括:
and()
and(Where<T, ID> first, Where<T, ID> second, Where<T, ID>... others)
and(int numClauses)
between(String columnName, Object low, Object high)
eq(String columnName, Object value)
exists(QueryBuilder<?, ?> subQueryBuilder)
ge(String columnName, Object value)
gt(String columnName, Object value)
idEq(ID id)
idEq(Dao<OD, ?> dataDao, OD data)
in(String columnName, Iterable<?> objects)
in(String columnName, Object... objects)
in(String columnName, QueryBuilder<?, ?> subQueryBuilder)
isNull(String columnName)
isNotNull(String columnName)
le(String columnName, Object value)
lt(String columnName, Object value)
like(String columnName, Object value)
ne(String columnName, Object value)
not()
not(Where<T, ID> comparison)
notIn(String columnName, Iterable<?> objects)
in(String columnName, Object... objects)
notIn(String columnName, QueryBuilder<?, ?> subQueryBuilder)
or()
or(Where<T, ID> first, Where<T, ID> second, Where<T, ID>... others)
or(int numClauses)
raw(String rawStatement)
prepare()
reset()
query()
queryRaw()
queryForFirst()
queryRawFirst()
countOf()
iterator()
3.6 使用select参数
select参数是一种使用在Where操作中的参数,这种参数可以直接指定为参数值(如上例子所示),或者作为一
个select参数对象。select参数可以用于后续设置参数值,他们会产生SQL ‘?’,类似于jdbc的占位符。
例如:
QueryBuilder<Account, String> queryBuilder = accountDao.queryBuilder();
Where<Account, String> where = queryBuilder.where();
SelectArg selectArg = new SelectArg();
// define our query as 'name = ?'
where.eq(Account.NAME_FIELD_NAME, selectArg);
// prepare it so it is ready for later query or iterator calls
PreparedQuery<Account> preparedQuery = queryBuilder.prepare();
// later we can set the select argument and issue the query
selectArg.setValue("foo");
List<Account> accounts = accountDao.query(preparedQuery);
// then we can set the select argument to another
// value and re-run the query
selectArg.setValue("bar");
accounts = accountDao.query(preparedQuery);
人们通常会试着创建一些具有参数的查询语句,并包含一些特定的符号,这些符号能自动生成sql语句,并导致
语法错误。在这种情况下可以使用SelectArg。此外,如果你的参数使用户输入的,那么使用SelectArgs可以保护你
的程序避免sql注入问题。其次,特定的数据类型可以使用一种内部的SelectArg对象,因为对象的String值对于数据
库而言是不可靠的。例如java.util.Date。
注意:SelectArg对象不能再一个对象的多列中使用,如果你想要在另外一列中使用SelectArg,你必须重新实例
化一个新的对象。
3.7 使用列参数
假如你使用QueryBuilder让一个值和列数据进行比较。那么可以使用ColumnArg:
例如:
QueryBuilder<Account, String> queryBuilder = accountDao.queryBuilder();
// list all of the accounts that have the same
// name and password field
queryBuilder.where().eq(Account.NAME_FIELD_NAME, new ColumnArg(Account.PASSWORD_FIELD_NAME));
List<Account> results = queryBuilder.query();
ColumnArg也可以携带一个表名,这种方式在JION查询中用于比较一个表中的列和另一个表中的列的数据时比较
有用。详情查看Building Join Queries一节。
3.8 构建连接查询
ORMLite支持基本的JION SQL查询,更多内容可查看JOIN documentation.
通过两个QueryBuilder对象创建一个join查询,其中一个在DAO中,用于返回你的对象,另一个DAO与第一个DAO
相关联。其中一个必须是另一个的外部属性,否则,jion方法会抛出异常。
例如:假设你想要获得一个account集合,并且这些account有一个订单的amount值大于100刀。则可以这样写:
QueryBuilder<Order, Integer> orderQb = orderDao.queryBuilder();
orderQb.where().ge("amount", 100.0F);
QueryBuilder<Account, Integer> accountQb = accountDao.queryBuilder();
// join with the order query
List<Account> results = accountQb.join(orderQb).query();
这里返回了所有的Account记录,并且,这些对象有一个对应的订单,这个订单有一个属性值大于100.
ORMLite也支持LEFTJOIN的概念,意思是,在上面的例子中,在上面的语句中,没有订单的account也会被返回。
但是,ORMLite不支持RIGHT JOIN 和 FULL JOIN的概念。
注意,其他的ORM库使用JOIN语句从多张表中获取数据填充外部对象属性和外部对象集合。ORMLite不支持这种特
性。你只能使用它从一张表中获得数据。