首先,我用这两个表创建了数据库:
Adresse和电话.
Adresse和电话.
我使用Ormlite在android中实现了外键,以便从Adresse到电话进行1对多的连接.
TELEPHONES的代码:
@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"); } } . . .
问题是,通常如果我想删除一个有一部或多部电话的地址,外键约束不应该让我这样做,但没有任何反应.
没有错误,没有警告,没有.
当我查看数据库中是否删除了该地址时,我发现该地址已删除,并且电话仍然存在,其中id_adresse与我删除的地址相关联.
我用Firefox中的sqlite Manager打开数据库,当我尝试做同样的事情时,发生错误告诉我,由于外键而无法做到这一点….
差点忘了:
CREATE TABLE "TELEPHONES" ("_id" INTEGER PRIMARY KEY NOT NULL,"ID_ADRESSE" INTEGER REFERENCES ADRESSE(_id))
所以我的最后一个问题是:
我做错了什么,因为在Android中我可以删除adresse?
我想要的是正确实现外键,不能删除该地址而不删除与该地址相关的电话.
更新:
我试过这样做:
public void openDataBase() { // Open the database String myPath = DB_PATH + DB_NAME; myDataBase = sqliteDatabase.openDatabase(myPath,sqliteDatabase.OPEN_READWRITE); if (!myDataBase.isReadOnly()) { myDataBase.execsql("PRAGMA foreign_keys=ON"); myDataBase.execsql("DELETE FROM ADRESSE WHERE _id=8"); } }
它确实删除了adresse以及相关的电话.
那么为什么要使用ormlite命令:
DeleteBuilder<Adresse,Integer> db = daoAdresse.deleteBuilder(); db.where().eq(Adresse.ID,8); daoAdresse.delete(db.prepare());
在tranzaction里面没有用?
更新2:
@Override public void onOpen(sqliteDatabase myDatabase){ String myPath = DB_PATH + DB_NAME; myDataBase = sqliteDatabase.openDatabase(myPath,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有关…
仍在搜索中..
解决方法
据我所知,支持外键限制,但您必须明确设置它.
This answer可能会帮助你.请注意,正如评论中所提到的,它仅适用于Android 2.2及更高版本.
UPDATE
您尚未定义操作如何更新/删除.在“电话”中,将列定义更新为以下内容:
@DatabaseField(canBeNull = false,columnDefinition = "integer references ADRESSE(_id) on delete cascade") private Adresse adresse;
并重新创建您的数据库.注意“on delete cascade”;当删除ADRESSE中的一行时,应删除TELEPHONES中的所有相关条目.