2

たとえば、次のスニペットでは、最初にデータベースからデータを読み取り、次にデータを変換し、最後に結果をデータベースに書き戻します。すなわち:

  1. データベースからデータを読み取り、レコードごとにクラス A に格納します。
  2. クラス A に格納されたデータをレコードごとに変換し、クラス B がこのジョブを実行します。
  3. すべての結果を QVariantList に保存し、バッチでデータベースに書き込みます。

問題は、クラス A、クラス B、およびクラス ReadTransWrite の間の密結合です。メンバー変数 A4 をクラス A に追加する場合、3 つのクラスを変更する必要があります。「//-->」で始まるコメントを参照してください

デカップリングする方法は?おすすめのパターンは?なにか提案を?

スニペット:

class A {
public: 
    void trans(QSqlQuery query){
        A1 = query.record().field("A1").value().toString();
        A2 = query.record().field("A2").value().toDate();
        A3 = query.record().field("A3").value().toInt();
        //--> A4 = query.record().field("A4").value().toDouble();
    }
public:
    QString A1;
    QDate A2;
    int A3;
    //--> double A4;
};

class B {
public:
    void trans(const A& a){
        B1 = A1;
        B2 = A2;
        B3 = A3;
        //--> B4 = A4;
    }
public:
    QString B1;
    QDate B2;
    int B3;
    //--> double B4;
};

class ReadTransWrite {
.....
    void do();
.....
}

void ReadTransWrite::do(){
    ....
    // prepare for batch insert into the database
    QVariantList B1s;
    QVariantList B2s;
    QVariantList B3s;
    //--> QVariantList B4s;

    A a;  // read record by record from data base
    B b;  // transform the results record by record

    QString sql_read = "select A1, A2, A3 from table0";
    //--> QString sql_read = "select A1, A2, A3, A4 from table0";
    QSqlQuery query_read;
    query_read.exec(sql_read);
    while(query_read.next()){
        a.trans(query_read);    // read record by record from data base
        b.trans(a);             // transform the results record by record
        B1s.push_back(b.B1);
        B2s.push_back(b.B2);
        B3s.push_back(b.B3);
        //--> B4s.push_back(b.B4);
    }

    QSqlQuery query_write;
    QString sql_write = "insert into table (B1, B2, B3) values (:B1, :B2, :B3)";
    //--> QString sql_write = "insert into table (B1, B2, B3, B4) values (:B1, :B2, :B3, :B4)";
    query_write.prepare(sql_write);

    query_write.bindValue(":B1",B1s);
    query_write.bindValue(":B2",B2s);
    query_write.bindValue(":B3",B3s);
    //--> query_write.bindValue(":B4",B4s);

    query_write.execBatch();
}
4

1 に答える 1

0

クラス A を次のように作成できます。

#include <QtCore/QVariant>
#include <QtSql/QSqlRecord>

class A 
{
public: 
    void fillFromRecord( const QSqlRecord& record )
    {
        for( int iColumn = 0; iColumn < record.count(); iColumn++ )
        {
            _contentMap.insert( 
                record.fieldName( iColumn ), 
                record.value( iColumn )
                );
        }
    }

    inline QVariantMap getContentMap() const { return _contentMap; }

private:
    QVariantMap _contentMap;
};

注: 私はそのコードのコンパイル エラーをテストしませんでしたが、少なくとも一般的なアイデアは得られるはずです。


そうすれば、データベースが変更されるたびにクラス A が変更されることはありません。

また、コメントでリンクされているデメテルの法則にもっと取り組むために、QSqlRecordではなく、を求める方法にも注意してください。QSqlQuerysehe

必要に応じてマップのタイプを変更できます。たとえば、名前ではなく列インデックスのみを格納し、追加の QMap 機能 (基本的に並べ替え) を必要としない QHash< int, QVariant > で十分な場合もあります。

于 2012-11-27T12:26:20.803 に答える