5

首先,我用这两个表创建了数据库:地址和电话。

我已经使用 Ormlite 在 android 中实现了外键,以便建立从 Adresse 到 Telephones 的连接 1。

电话的代码:

@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;
    }  
}

地址的代码:

@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");
        }
    }
.
.
.

问题是,通常如果我想删除一个有一个或多个电话的地址,外键约束不应该让我这样做,但什么也没有发生。没有错误,没有警告,什么都没有。当我在数据库中查看我是否删除了地址时,我看到地址已被删除,而电话仍然存在,id_adresse 链接到我已删除的那个。

我已经用 Firefox 的 SQLite Manager 打开了数据库,当我尝试做同样的事情时,出现一个错误,告诉我,由于外键无法做到这一点......

差点忘了:

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; 

并重新创建您的数据库。注意“on delete cascade”;当 ADRESSE 中的一行被删除时,TELEPHONES 中的所有相关条目都应该被删除。

于 2012-11-21T12:52:30.327 回答