2016-06-20 12 views
0

私はQtの例 "表モデルの例" という例でQtの表モデル例

で探していますが、connection.h中のcreateConnection()メソッドは、次のコードが含まれています私のコードでこの例を複製しました。私はそれについて2つのことを理解していません。

  1. ローカル変数dbは、createConnection()関数(RAIIを参照)の最後で破棄されます。私のデータベースは初期化する必要はなく、 "db"変数を使用していないので、なぜこのコードが必要なのかわかりません。しかし、私がそれを削除すると、私のプログラムは私の既存のデータベースからの読み込みに失敗します。 dbの破壊がデータベースを閉じて、それを利用不可能にすることが期待されます。しかし、私はdb変数に触れていないので、なぜデータベースにアクセスする前に作成して破壊する必要がありますか?どこでもdb変数を使用せず、コードが呼び出される前に破棄されるので、なぜcreateConnection()関数を呼び出す必要があるのか​​分かりません。一方、私はどのようにデータベースを開き、例外的に安全なRAIIコードを持つ変数破壊を引き起こすのか分かりません。

  2. db.open()が失敗することはありません。私はデータベースを持っていない場合、それはそれを作成し、空白のものを開きます。私はデータベースを持っていればそれを開きます。私はデータベースを持っていて、なんらかの理由でオープンに失敗した場合、作成したくないので、何かが間違っているのでエラーが欲しい。空のデータベースを開くことは、私にとっては厄介なことに過ぎません。このケースをどうやって処理するのですか?

私はQt初心者ですが、C++で非常に経験があります。このコードは私にはほとんど意味がありません。私はdb変数の寿命がオープンデータベースの寿命であると期待します。例でコード化されているように、私はこのコードがどのようにリソースリークを起こしていないか見当たりません。私が知ることから、dbを初期化すると、何らかの種類のグローバルリソースがオープンし、db変数が破棄されてリークが発生した後でもオープンされたままになります。

これは非常に混乱しています。

Thx。

H Osタイル

+0

'QSqlDatabase'はかなり奇妙なクラスです。そのドキュメントを読んでください:それはあなたが思うように行動しません。 RAIIクラスではありません。 –

答えて

0

これは単なる小さな例です。

  1. QSqlDatabase::addDatabase("QSQLITE");別の接続に名前を付け、明示的ではない、後続のクエリで使用されるデフォルトの接続を作成します。スコープの終了時に接続は破棄されません。この例では、createConnection()がinMemoryデータベースの初期化に使用されます。接続は後でQSqlDatabase::database()を使用して取得できます。標準的なアプリケーションでは、おそらくQSqlDatabase dbをクラスメンバとして保持します。

  2. inememory dbを使用すると、SQLiteファイルベースのdbと同じように空のdbが作成されます。既存のファイル(db)を確認する場合は、QFile::exists(QString path)を使用してください。あなたがそうでなければあなただけのデフォルトのデータベース接続を上書きしている。あなたは、リークを持っているでしょうQSqlDatabase::addDatabase("QSQLITE","anotherConnectionName");に異なる接続名を(多くのデータベースをオープンした場合

。はQApplication自体は、接続を維持します。彼らはQSqlDatabase::removeDatabase()を使用して明示的に削除できます。

+0

ここであなたが言っていることを理解するのは難しいです。私はinMemory dbが物事を異ならせる理由は不明だ。私のコードは例から複製されていて、 "inMemory"は何も作成されず、データベースもすべて同じように作成されます。 SQLite_OPEN_READWRITEはデータベースが既に存在していなければならないエラーを返します。そうでない場合はエラーが返されます。また、dbをメンバにすると、変数からラッパーのインスタンスに移動するように見えるので、どのように役立つのか分かりません。 Qtのようなサウンドはスレッドセーフではなく、例外をサポートしていませんか?私は今、私の理解の中ではより悪いと思う。 –

+0

文書では、クラスごとにスレッドの安全性が示されています。例外はサポートされていますが、古いコンパイラでの互換性の問題のために広く実装されていません。これはおそらくQt 5.7では多く変わります。 –

+0

KubaOberが述べたようにQSqlDatabaseは特別なものです。 'QSqlQuery'またはそれに類するクラス(' QSqlTable'、...)を作成してデータベースハンドルを提供しないと、Qtは自動的にデフォルトの接続を使います。これは実際にはデータベースへの問い合わせを非常に簡単にします。 SQL接続自体はスレッドセーフではありません。データベースに直接問合せを行うスレッドごとに接続を開く必要があります。 –

0

QSqlDatabaseはかなり奇妙なクラスです。そのドキュメントを読んでください。接続は継続され、QSqlDatabaseがそのハンドルです。接続には名前が付けられ、addDatabaseは指定された名前で接続を返し、存在しない場合はオプションで接続を作成します。任意の数のQSqlDatabaseオブジェクトが1つの接続を表すことができます。

sqliteのメモリ内データベースはプロセス固有のものなので、要求時に作成しない点はほとんどありません。事前に作成する唯一の方法は、プロセスから直接sqlite apiを使用することです。これらのデータベースは保持されません。ここの行動はかなり賢明です。

+0

Retype:私のデータベースはディスク上にあり、アプリケーションが起動する前に存在していなければならないので、動作は分かりません。不足しているデータベースを確実に診断し、ユーザーに報告する必要があります。複数のプログラムが同時に起動される場合も、これは真です。このドキュメントでは、これらの関数のスレッドセーフについては何も言及していません。見つからない場合はエラーを報告せず、データベースをディスクに作成するため、トピックのドキュメントの無音に関係なく、スレッドセーフであってはなりません。リソースが漏れて、安全性も例外ではないことを悲しんでいる。 Qtは良いC++ライブラリのようにRAIIに固執していたはずです。 –

+0

@HOsTile一度に1つのスレッドからの接続を使用する限り、あなたは良いです。あなたの質問は、ディスク上のデータベースを扱っていません。あなたが何か他のものを求めたいならば、それは聖なるものすべての愛のためにそうしてください。 –

+0

@HOsTile私はあなたの心を読むことができません。あなたが実際に何をしているのかを説明するためにコメントしなければならない場合(すなわち、メモリ内のデータベースについては何もない)、あなたの質問には修正が必要であることが示されます... –