查询

QtDao的查询以实体类(生成器插件根据配置xml文件生成的模型类)查询为主,使用函数_select<E>返回一个SelectBuild<E>对象,通过传入模板参数指定需要查询的表:

template<typename E>
SelectBuilder<E> dao::_select<E>()

通过SelectBuild<E>设置查询条件,如 column()filter()with(),最后调用build()函数创建Select<E>对象完成最终查询:

template<typename E>
Select<E> dao::_select<E>().build()

column()

  • 字段设置

template<typename E>
template<typename T>
SelectBuilder<E> dao::_select<E>().column(const EntityField<T>& field, ...);

column()函数用于设置查询的实体类字段,通常,查询结果为实体的一个对象或列表,只有被设置到column()函数中字段的值才会被设置到实体对象对应字段中,其他字段将被设置为默认值(若配置)或随机值,相当于使用 'select field from Table' 而不是 'select * from Table'

注意:默认情况下,忽略调用column()函数将导致所有字段被查询并设置。

如下,查询所有用户的姓名name和年龄age

User::Fields field;
UserList user = dao::_select<User>().column(field.name, field.age).build().list();

等同于sql语句:

select name, age from User

在此结果列表容器中,只有nameage字段有效,其他字段为默认值或随机值。

  • 函数字段

template<typename E>
SelectBuilder<E> dao::_select<E>().column(const FunctionCondition& field, ...);

column()函数还可以用于读取_fun()的返回结果,如下计算所有用户分数score的总和:

User::Fields field;
User user = dao::_select<User>()
    .column(_fun("sum(%1) as sumscore").field(field.score))
    .build().unique();

等同于sql语句:

select sum(score) as sumscore from User

_fun()的使用后面将做详细说明,在这里,函数作为字段设置时,其as别名将设置到实体对象的__extra变量中,如下读取上述的总分数:

int score = user.__getExtra<int>("sumscore");
  • 混合字段

当然,字段和函数可以混合使用,可以联级使用,若想读取所有字段又想添加函数,可以使用 columnAll 函数,如下几种用法:

User::Fields field;

//字段函数混合使用
User user = dao::_select<User>()
    .column(field.name, _fun("max(%1) as maxscore").field(field.score))
    .build().unique();

//联级调用
User user = dao::_select<User>()
    .column(field.name)
    .column(field.age)
    .column(_fun("max(%1) as maxscore").field(field.score))
    .build().unique();

//所有字段与函数
User user = dao::_select<User>()
    .columnAll()
    .column(_fun("max(%1) as maxscore").field(field.score))
    .build().unique();

filter()

  • 查询条件设置

template<typename E>
SelectBuilder<E> dao::_select<E>().filter(const EntityCondition& condition, ...);

filter()函数用于设置查询条件,传入的参数为字段与值运算的EntityCondition类型结果。在设置条件时,应该使用生成器生成的模型类中E::Fields成员表示的字段,其中每个成员都是EntityField<T>类型,该类型重载了部分运算符如:=, !=, >, >=, <, <=

注意:重载后的运算符与值运算时严格使用与字段一致的参数类型,字段声明为QString类型,则运算对象必须是QString类型。

如下,查询分数score大于100的用户:

User::Fields field;
UserList user = dao::_select<User>()
    .filter(field.score > 100)
    .build().list();
  • 查询条件的组合

filter函数传入的条件可以连续设置多个,多个之间用逗号连接等同于sql中 and 连接符,显式使用 _and()_or() 函数可以组合多个条件。另外,filter也可以联级调用,等同于使用 and 连接符。

注意:_and()_or() 函数连接时是对函数各个参数条件之间使用对应的连接符进行连接,并且连接后会自动添加括号运算符。

User::Fields field;
UserList user = dao::_select<User>()
    .filter(field.name.like("Alice%"))
    .filter(
        field.age >= 18, 
        _or(field.score > 200, _and(field.score > 50, field.score <= 100))
    )
    .build().list();

等同于sql语句:

select *from User where name like 'Alice%' and age >= 18 and (score > 200 or (score > 50 and score <= 100))

_and()_or() 函数还可以用于临时条件的存储:

UserList findPassingUsers(QString keywords) {
    User::Fields field;

    auto condition = _and(
        field.age >= 18, 
        _or(field.score > 200, _and(field.score > 50, field.score <= 100))
    );
    if (!keywords.isEmpty()) {
        condition = _and(field.name.like("Alice%"), condition);
    }

    return dao::_select<User>().filter(condition).build().list();
}

EntityField<T>类型还支持以下预设的条件函数:

  • like/glob

同sql语句中的like/glob,用于模糊查找条件,通常情况下,仅QString类型才会使用它,如下所示:

User::Fields field;
UserList user = dao::_select<User>()
    .filter(field.name.like("%Alice%"))
    .build().list();
  • in

同sql语句中的in字句,用于范围查找。传入类型为QList<T>,其中T与字段类型相匹配。如下所示:

auto scores = QList<int>() << 50 << 100 << 150;

User::Fields field;
UserList user = dao::_select<User>()
    .filter(field.score.in(scores))
    .build().list();
  • between

同sql语句中的between字句,用于范围查找。传入字段相匹配类型参数,如下所示:

User::Fields field;
UserList user = dao::_select<User>()
    .filter(field.score.between(50, 100))
    .build().list();
  • lsNull/notNull

判断null的条件:

User::Fields field;
UserList user = dao::_select<User>()
    .filter(field.name.notNull())
    .build().list();
  • 自定义条件

template<typename E>
SelectBuilder<E> dao::_select<E>().filter(const FunctionCondition& function, ...);

当需要使用自定义的条件时,使用_fun()创建自定义查询条件,如下所示:

User::Fields field;
User user = dao::_select<User>()
    .filter(field.name == "Alice"))
    .filter(_fun("sum(%1) as sumscore").field(field.score))
    .build().one();

with()

template<typename E>
SelectBuilder<E> dao::_select<E>().with(const ConditionConstraint& constaint, ...);

with()函数用于对查询结果的限制,如sql原语中的'limit''order by''group by''having'子句等。

  • limit

_limit()函数用于限制返回结果数量,同sql语句limit,如下:

//输出20条结果
User::Fields field;
UserList user = dao::_select<User>()
    .filter(field.score > 100)
    .with(_limit(20))
    .build().list();

//从第5个结果开始,输出20条结果
User::Fields field;
UserList user = dao::_select<User>()
    .filter(field.score > 100)
    .with(_limit(5, 20))
    .build().list();
  • order by

_orderBy()函数用于排序,同sql语句order by,如下:

User::Fields field;
UserList user = dao::_select<User>()
    .filter(field.score > 100)
    .with(_orderBy(field.name, field.age))
    .build().list();
  • group by / having

_groupBy()函数用于对查询结果进行分组,_having()函数用于设置分组结果的过滤条件,如下:

User::Fields field;
UserList user = dao::_select<User>()
    .with(_groupBy(field.name, field.age), _having(field.score > 100))
    .build().list();

User::Fields field;
UserList user = dao::_select<User>()
    .with(_groupBy(field.name))
    .with(_having(_fun("count(%1) > 2").field(field.id)))
    .build().list();
  • _constraint()

_constraint()函数用于连接结果限制函数。通常情况下,多个结果限制函数可以连续使用:

User::Fields field;
UserList user = dao::_select<User>()
    .with(_groupBy(field.name), _limit(5))
    .build().list();

在需要临时存储限制条件时,使用_constraint()函数组合:

UserList getUserNames(int limitSize) {
    User::Fields field;

    auto condition = _groupBy(field.name);
    if (limitSize > 0) {
        condition = _constraint(condition, _limit(limitSize));
    }

    return dao::_select<User>().with(condition).build().list();
}

可选择的

对于以下条件设置函数,提供了可选择的设置方法:columnset(update)、filteron(join)、with。如下例子所示,设置like条件的前提是keywords不能为空:

QString keywords = "Alice";
User::Fields field;
UserList user = dao::_select<User>()
    .filter(!keywords.isEmpty(), field.name.like("%" + keywords + "%"))
    .build().list();

按列读取结果

Select查询的 uniqueonelist 和Join查询的 list 函数添加了使用列提取结果的重载函数,例如list的声明如下:

template<typename T>
QList<T> list(const EntityField<T>& field);

template<typename T, typename K>
QList<QPair<T, K>> list(const EntityField<T>& field1, const EntityField<K>& field2);

template<typename T, typename... Args>
QList<std::tuple<T, typename Args::Type...>> list(const EntityField<T>& field, const Args&... args);

使用时如下所示:

User::Fields field;
QList<QString> user = dao::_select<User>()
    .filter(field.score > 100)
    .with(_limit(5, 20))
    .build().list(field.name);

QList<QPair<QString, int>> user = dao::_select<User>()
    .filter(field.score > 100)
    .with(_limit(5, 20))
    .build().list(field.name, field.age);

QList<std::tuple<QString, int, int>> user = dao::_select<User>()
    .filter(field.score > 100)
    .with(_limit(5, 20))
    .build().list(field.name, field.age, field.score);

按列读取结果与返回一个对象的查询相比,减少了对象的创建,通常情况下这并不会带来过多的效率提升,仅仅是简化了返回的结果集,在大量数据读取时考虑配合使用column()函数以提升查询效率。

读取表所有数据

使用以下代码可以将表所有数据读出:

UserList users = dao::_selectAll<User>();

count

使用dao::_count<T>()函数对查询结果计数,查询条件的使用与dao::_select<T>()函数一致。对于_count函数,其返回类型为CountBuilder<E>,直接调用count()函数读取结果记数:

User::Fields field;
int count = dao::_count<User>()
    .filter(field.score > 100)
    .count();

results matching ""

    No results matching ""