5

まず、AdresseとTelephonesの2つのテーブルを使用してデータベースを作成しました。

AdresseからTelephonesまで1対多の接続を確立するために、Ormliteを使用してAndroidに外部キーを実装しました。

電話のコード:

@DatabaseTable(tableName = "TELEPHONES")
public class Telephone {
    public static final String TABLE_NAME = "TELEPHONES";
    public static final String ID_ADRESSE = "ID_ADRESSE";

    @DatabaseField(generatedId = true)
    private Integer _id;

    @DatabaseField(canBeNull = false, foreign = true,columnName = ID_ADRESSE)
    private Adresse adresse; 
        .
        .
        .
        .
    public Adresse getAdresse() {
        return adresse;
    }

    public void setAdresse(Adresse adresse) {
        this.adresse = adresse;
    }  
}

ADRESSEのコード:

@DatabaseTable(tableName = "ADRESSE")
public class Adresse {

    public static final String TABLE_NAME = "ADRESSE";
    public static final String ID = "_id";

    @DatabaseField(generatedId = true)
    private Integer _id;

    @ForeignCollectionField(eager = false)
    private ForeignCollection<Telephone> telephones;
}

SQLiteデータベースが外部キーを実装していることも読みましたが、データベースを開くたびにそれらを有効にして、データベースを変更する必要があります。だから私はこのコードを追加しました:

.
.
.
    public void openDataBase() {
        // Open the database
        String myPath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READWRITE);
        if (!myDataBase.isReadOnly()) {
            myDataBase.execSQL("PRAGMA foreign_keys=ON;");
        } else {
            System.out.println("database is open as read only");
        }
    }
.
.
.

問題は、通常、1つ以上の電話を持っているアドレスを削除したい場合、外部キー制約によってそれを実行できないようにする必要がありますが、何も起こりません。エラーなし、警告なし、何もありません。また、データベースを調べて住所を削除したかどうかを確認すると、住所が削除されており、電話はまだそこにあり、id_adresseは削除したものにリンクされています。

FirefoxからSQLiteManagerを使用してデータベースを開きましたが、同じことを実行しようとすると、外部キーが原因で実行できないというエラーが発生します。

ほとんど忘れてしまった:

SqliteのテーブルTelephoneのコード:

CREATE TABLE "TELEPHONES" 
("_id" INTEGER PRIMARY KEY  NOT NULL,"ID_ADRESSE" INTEGER REFERENCES ADRESSE(_id))

だから私の最後の質問は:

Androidではアドレスを削除できるので、私が間違ったことは何ですか?

私が欲しいのは、外部キーを正しく実装することです。アドレスに関連する電話を最初に削除せずにアドレスを削除することはできません。

更新:私はこれをやってみました:

public void openDataBase() {
    // Open the database
    String myPath = DB_PATH + DB_NAME;
    myDataBase = SQLiteDatabase.openDatabase(myPath, null,
            SQLiteDatabase.OPEN_READWRITE);
    if (!myDataBase.isReadOnly()) {
        myDataBase.execSQL("PRAGMA foreign_keys=ON");
        myDataBase.execSQL("DELETE FROM ADRESSE WHERE _id=8");
    } 
}

そしてそれはアドレスと関連する電話も削除します。

では、なぜormliteコマンドを使用するのですか?

    DeleteBuilder<Adresse, Integer> db = daoAdresse.deleteBuilder();
db.where().eq(Adresse.ID, 8);
daoAdresse.delete(db.prepare());

トランザクションの中はうまくいきませんでしたか?

更新2:

@Override
    public void onOpen(SQLiteDatabase myDatabase){
        String myPath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READWRITE);
        if (!myDataBase.isReadOnly()) {
            myDataBase.execSQL("PRAGMA foreign_keys=ON");
            System.out.println("open database with pragma on from onOpen");
        } else {
            System.out.println("database is open as read only from onOpen");
        }

    }

私はこれを行いました、そして私は他の方法の代わりにこの方法が使われているというメッセージを受け取ります、しかし電話なしで私のアドレスを削除しているだけです。だから私は本当にわかりません。それはどこかで問題になっているに違いありません、そして私はそれがDeleteBuilderと関係があると思います...

まだ探している..

4

1 に答える 1

2

私の知る限り、外部キー制限はサポートされていますが、明示的に設定する必要があります。この答えはあなたを助けるかもしれません。そこのコメントに記載されているように、Android 2.2 以降でのみ機能することに注意してください。

アップデート

更新/削除時に行うアクションを定義していません。でTelephone、列の定義を次のように更新します。

@DatabaseField(canBeNull = false, foreign = true, columnDefinition = "integer references ADRESSE(_id) on delete cascade")
private Adresse adresse; 

そして、データベースを再作成します。「カスケード削除時」に注意してください。アドレスの行が削除されると、TELEPHONES のすべての関連エントリが削除されます。

于 2012-11-21T12:52:30.327 に答える