SQL Programming (4):Using the SQL Model Classes

    除了QSqlQuery类以外,Qt还提供了三个更复杂的访问数据库的类,QSqlQueryModel ,QSqlTableModel, QSqlRelationalTableModel.

  • QSqlQueryModel : 一个基于任意SQL语句的只读模型
  • QSqlTableModel:一个针对单表的可读写模型
  • QSqlRelationalTableModel: 一个支持外键的QSQLTableModel的子类

   以上的三个类都源于QAbstractTableModel类(这个类继承自QAbstractItemModel),通过和一个Item View类结合(比如QListView、QTableView),使得从一个数据库中呈现数据的更加的简单。在Presenting Data in a Table View 章节,这一过程将会被详细的解释。

     使用这些类也能够让你的代码更加方便的更改为其他的数据源。举个例子,如果你开始使用的是QSqlTableModel类,之后觉得使用XML文档来替代之前使用的数据库来存储数据,那么这本质上只是一个数据模型替换为另一个的问题。

The SQL Query Model

    QSqlQueryModel 提供了基于一条SQL语句的只读模型。

例子:

 
 
1
2
3
4
5
6
7
8
  QSqlQueryModel model ;
model . setQuery ( "SELECT*FROMemployee" ) ;
for ( int i = 0 ; i < model . rowCount ( ) ; ++ i ) {
  int id = model . record ( i ) . value ( "id" ) . toInt ( ) ;
  QString name = model . record ( i ) . value ( "name" ) . toString ( ) ;
  qDebug ( ) << id << name ;
}

    在调用了 QSqlQueryModel::setQuery()函数设置了查询语句后,你可以使用QSqlQueryModel::record(int)来获取指定的查询记录。当然,你也可以使用QSqlQueryModel::data()或者其他的继承自QAbstractItemModel的函数。

    例外,setQuery()的一个重载函数支持两个参数,一个是一个QSqlQuery的对象,另外一个是要操作的结果集,也就是数据库。这可以让你更好的使用QSqlQuery的一些特性(比如,prepared queries)。

The SQL Table Model

    QSqlTableModel提供了一个一次可以操作单个SQL表的可读写模型。

栗子:

 
 
1
2
3
4
5
6
7
8
9
10
  QSqlTableModel model ;
model . setTable ( "employee" ) ;
model . setFilter ( "salary>50000" ) ;
model . setSort ( 2 , Qt :: DescendingOrder ) ;
model . select ( ) ;
for ( int i = 0 ; i < model . rowCount ( ) ; ++ i ) {
QString name = model . record ( i ) . value ( "name" ) . toString ( ) ;
int salary = model . record ( i ) . value ( "salary" ) . toInt ( ) ;
qDebug ( ) << name << salary ;
}

    QSqlTableModel针对QSqlQuery,在单表的操作修改上提供了更好的交互方式。这样就使得coder只需要很少的代码同时摆脱了SQL语法的束缚就能够完成数据操作。

     使用QSqlTableModel:record()函数可以获得表中的指定行,使用 QSqlTableModel:setRecord()来修改数据。举个例子,下面的代码会将每个员工的工资提高10%:

 
 
1
2
3
4
5
6
7
8
for ( int i = 0 ; i < model . rowCount ( ) ; ++ i ) {
QSqlRecord record = model . record ( i ) ;
double salary = record . value ( "salary" ) . toInt ( ) ;
salary *= 1.1 ;
record . setValue ( "salary" , salary ) ;
model . setRecord ( i , record ) ;
}
model . submitAll ( ) ;

    你也可以使用QSqlTableModel:data()和QSqlTableModel:setData()(继承自QAbstractItemModel)来获取数据。例如,下面是如何使用setData()函数来更新一条记录:    

 
 
1
2
model . setData ( model . index ( row , column ) , 75000 ) ;
model . submitAll ( ) ;

    以下是如何插入并填充一行数据:

 
 
1
2
3
4
5
  model . insertRows ( row , 1 ) ;
model . setData ( model . index ( row , 0 ) , 1013 ) ;
model . setData ( model . index ( row , 1 ) , "PeterGordon" ) ;
model . setData ( model . index ( row , 2 ) , 68500 ) ;
model . submitAll ( ) ;

    以下是如何删除五个连续的行数据:

 
 
1
2
model . removeRows ( row , 5 ) ;
model . submitAll ( ) ;

    函数QSqlTableModel:removeRows()的第一个参数是第一个要被删除行的索引。    

    当你修改完成一行记录后,应该调用QSqlTableModel::submitAll()函数来保证所有的数据改变都被写入数据库。

    至于在什么时候应该调用submitAll()函数取决于表的编辑策略(edit strategy)。默认的编辑策略是QSqlTableModel::OnRowChange,即在用户选取不同的行后,向数据库提交更改。其他的策略还有QSqlTableModel::OnManualSubmin(即缓存所有数据改变,直到调用submitAll()函数),QSqlTableModel::OnFieldChange(不缓存更改)。当QSqlTableModel和View类一起使用时,这些策略是非常有帮助的。

    QSqlTableModel::OnFieldChange 意味着你永远不会显示的调用submitAll()函数。尽管如此,这里面也存在这两个误区:

  1. 没有任何缓存,意味着性能会显著下降;
  2. 当你试图增加一个主键时,你来不及对它填充数据。

The SQL Relational Table Model

    QSqlRelationalTableModel 是对QSqlTableModel类的扩展,它提供了对外键的支持。一个外键是指一个表中的字段和另外一个表的主键存在一对一的映射关系。举个例子,如果book表中有一个名为authorid的字段指的是author表中的id字段(id字段是主键),那么authorid就是一个外键。

        

        

        第一副截图是在QTableView里使用了一个简单的QSqlTableModel。外键(city和Country)并没有被转化为可读值。第二幅截图使用的是QSqlRelationalTableModel,外键值被解析为可读的文本字符。

    下面的代码片段演示了如何创建一个QSqlRelationalTableModel:

 
 
1
2
3
model -> setTable ( "employee" ) ;
model -> setRelation ( 2 ,  QSqlRelation ( "city" ,  "id" ,  "name" )) ;
model -> setRelation ( 3 ,  QSqlRelation ( "country" ,  "id" ,  "name" )) ;

    详细用法,请查看QSqlRelationalTableModel的文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值