在Android中具有一对多和多对多关系的INSERT和SELECT语句

时间:2013-01-08 03:03:27

标签: android sql sqlite persistence

我正在使用SQLite数据库来存储可用于重建我正在开发的应用程序中使用的某些对象的数据。我正在存储CheckIns,Recipients和ContactMethods。

这些对象如下:

CheckIn <--many -- to -- many--> Recipient
Recipient <--one -- to -- many--> ContactMethod

在Java中,这些对象的字段定义如下:

public class CheckIn {
    private int id;
    private boolean isEnabled;
    private Date startTime;
    private Repetition repetition; 
    private Set<Recipient> recipients;
}

public class Recipient {    
    private String name;
    private Set<ContactMethod> contactMethods;    
}

public class ContactMethod {    
    private String type;
    private String address;    
}

我为这些对象提出的数据库模式定义如下:

CREATE TABLE checkIn(
  _id               INTEGER PRIMARY KEY AUTOINCREMENT,
  isEnabled         INTEGER,
  startTime         INTEGER,
  repetitionNum     INTEGER,
  repetitionUnits   TEXT
);

CREATE TABLE recipient(
  _id               INTEGER PRIMARY KEY AUTOINCREMENT,
  name              TEXT
);

CREATE TABLE contactMethod(
  _id                       INTEGER PRIMARY KEY AUTOINCREMENT,
  type                      TEXT,
  address                   TEXT,
  recipientID               INTEGER,
  FOREIGN KEY(recipientID) REFERENCES recipient(_id) ON DELETE CASCADE
);

CREATE TABLE checkIn_recipient(
  checkInID         INTEGER,
  recipientID       INTEGER,
  FOREIGN KEY(checkInID) REFERENCES checkIn(_id),
  FOREIGN KEY(recipientID) REFERENCES recipient(_id)
);

我有两个问题。

1。如何有效地将CheckIn与其相关对象一起插入数据库?

更具体地说,如果我在Java中有一个CheckIn对象,尚未提交到数据库,我如何构造一个INSERT语句,将CheckIn插入CheckIn表,还将新的CheckIn关系存储到一个或更多收件人?似乎要将关系存储到收件人,我需要知道尚未设置的checkIn._id,因为CheckIn还没有输入到数据库中。

2。在Android中,重建CheckIn对象的最佳方法是什么,例如,从数据库查询?

我想我知道获取正确数据所需的SQL查询:

SELECT checkIn.*, recipient.name, contactMethod.type, contactMethod.address
FROM checkIn
JOIN checkIn_recipient
    ON (checkIn._id = checkIn_recipient.checkInID)
JOIN recipient
    ON (checkIn_recipient.recipientID = recipient._id)
JOIN contactMethod
    ON (recipient._id = contactMethod.recipientID)

此查询将获取包含为数据库中的每个CheckIn和Recipient构建对象所需的所有信息的数据行,并且我知道如何获取将遍历这些行的Cursor对象。但是,由于单个CheckIn所需的数据出现在多行上,因此我对构造单个CheckIn对象的最佳方法感到困惑。如果我正在尝试编写一个类似public Set<CheckIn> getAllCheckIns()的方法来返回一组存储在数据库中的所有CheckIns,我是否需要运行上面的查询,然后使用相同的checkIn._id循环遍历每一行,并且在该循环中,每一行都具有相同的recipient._id,依此类推?有没有更好的方法呢?

对不起,我很抱歉。从今天早上开始,我只在单表数据库之外使用SQL,我不想遗漏任何重要信息。如果我错过了什么,请告诉我。

1 个答案:

答案 0 :(得分:3)

对问题1的回答:有两种可能的方法。

一个。您可以找到插入行的ID,并使用它插入第二个表。如果您使用的是此处记录的Android Insert方法,则可以找到插入行的ID: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#insert%28java.lang.String,%20java.lang.String,%20android.content.ContentValues%29

在这里,您必须确保所有数据库表都已提交或未提交。

湾您可以创建触发器。触发器是在发生指定数据库事件时自动执行的数据库操作。 了解如何创建触发器:http://www.sqlite.org/lang_createtrigger.html

因此,例如您可以创建一个AFTER INSERT触发器,当在check in table中插入一行时将触发该触发器。然后在该触发器中,您可以将行插入另一个表中。 触发触发器后,您可以访问新插入的行。

回答问题2: 我通常会做以下事情:

  • 从表1中选择 - 签入表
  • 迭代光标并准备Check In对象。
  • 在循环中,从表2 - 收件人表
  • 中选择
  • 迭代收件人表并准备签入对象。

这将涉及太多的数据库选择。

或者,您可以选择所有数据一次,然后迭代以准备对象。

我想说的是你必须迭代:D