Android 房间 - CASCADE 依赖于 table 用于 DELETE 并保持 INSERT 操作不可触及?

Android Room - CASCADE in dependent table for DELETE and keep untouchable for INSERT operation?

我有两个 tables - usersconversations。许多 users 可能参加一个 conversation,一个 user 可能是许多 conversations

的成员
@Entity(tableName = "users")
public class User {
    @NonNull
    @PrimaryKey
    @ColumnInfo(name = "userId")
    private String id;  
    ...
    //Getters and setters  
}  

@Entity(tableName = "conversations")
public class Conversation {
    @NonNull
    @PrimaryKey
    @ColumnInfo(name = "uuid")
    private String id;  
    ...
    //Getters and setters  
}

追踪哪个user参与哪个conversation我用第三个table:

@Entity(tableName = "user_conversation", indices = {@Index(value = {"userId", "conversationUuid"}, unique = true)},
    primaryKeys = {"userId", "conversationUuid"},
    foreignKeys = {
            @ForeignKey(onDelete = CASCADE, entity = User.class,         parentColumns = "userId", childColumns = "userId"),
            @ForeignKey(onDelete = CASCADE, entity = Conversation.class, parentColumns = "uuid",   childColumns = "conversationUuid")
    })
public class JoinUserConversation {
    @NonNull
    private String userId;

    @NonNull
    private String conversationUuid;
    ...
    //Getters and setters
}

Dao 个对象:

@Dao
public interface UsersDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insert(User user);
    ...
}

@Dao
public interface ConversationsDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    long insert(Conversation conversation);
    ....
}

当我从他们的 table 中 delete 一个 userconversation 时,我也需要从 user_conversation 中删除它们,我使用 onDelete = CASCADE 用于此目的。但是当我insert一个userconversation到他们table的时候我不需要删除 他们来自 user_conversation。但据我了解,如果插入实体已经存在于 table 和相应的 user 或 [=18= 中,则 insert@Insert(onConflict = OnConflictStrategy.REPLACE) 将通过 delete 执行] 将从 user_conversation table 中删除。 如何防止 user_conversationinsert 上发生变化?

我相信您可以通过检查要插入的行的 ID 来完成您想要的操作,如果存在则更新,如果不存在则插入。

  • 请注意,我尝试将 deferred = true@Transaction 一起使用,但由于 CASCADE 执行了它应该执行的操作,所以没有冲突。

例如,对于用户:-

添加

@Query("SELECT count() FROM users WHERE userId = :userId")
int getUserCount(String userId);

@Update()
int updateUser(User user);

然后有个方法,比如:-

private void upsertUser(User u) {
    if (mWTDao.getUserCount(u.getId()) > 0) {
        mWTDao.updateUser(u);
    } else {
        mWTDao.insert(u);
    }
}
  • mWTDao 是所有 Dao 存在的地方(示例相同)

例子

考虑以下摘录(来自测试代码):-

    ......... other code

    upsertUser(new User("userid001","Fred"));
    upsertUser(new User("userid002","Mary"));
    upsertUser(new User("userid003","Jane"));
    upsertUser(new User("userid004","Tom"));

    mWTDao.insert( new Conversation("c001","SUBJECT A"));
    mWTDao.insert( new Conversation("c002","SUBJECT X"));

    mWTDao.insert(new JoinUserConversation("userid001","c001"));
    mWTDao.insert(new JoinUserConversation("userid003","c001"));

    mWTDao.insert(new JoinUserConversation("userid002","c002"));
    mWTDao.insert(new JoinUserConversation("userid004","c002"));

    logAllInfo("PRE");

    upsertUser(new User("userid001","Harry"));
    upsertUser(new User("userid002","Gertrude"));
    logAllInfo("POST");

}

private void upsertUser(User u) {
    if (mWTDao.getUserCount(u.getId()) > 0) {
        mWTDao.updateUser(u);
    } else {
        mWTDao.insert(u);
    }
}


private void logAllInfo(String tag) {

    Log.d("INFO" + tag,"Logging Conversations via Original Mapping Table ");

    for (JoinUserConversation juc: mWTDao.getAllJUC()) {
        Conversation c = mWTDao.getConversation(juc.getConversationUuid());
        User u = mWTDao.getUser(juc.getUserId());
        Log.d("INFO" + tag,"\tFor Conversation " + c.getTitle() + "ID is (" + c.getId() + ") User is " + u.getName() + " ID is (" + u.getId() + ")");
    }

    Log.d("MAPINFO" + tag,"Logging Users ");

    for (User u: mWTDao.getAllUsers()) {
        Log.d("USERINFO" +  tag,"\tID is " + u.getId() + " Name is " + u.getName());
    }

    Log.d("CONVINFO","Logging Conversations");
    for (Conversation c: mWTDao.getAllConversations()) {
        Log.d("CONVINFO" + tag,"\tID is " + c.getId() + " Ttitle is " + c.getTitle());
    }
}
  • 这会添加 4 个用户(使用 upsertUser 方法)和 2 个对话以及一些 user_conversations
  • 显示信息
  • 然后尝试使用 upsertUser 方法添加现有用户
  • 再次显示信息,显示现有用户已更新。

结果

2019-09-18 08:14:19.214  D/INFOPRE: Logging Conversations via Original Mapping Table 
2019-09-18 08:14:19.220  D/INFOPRE:     For Conversation SUBJECT AID is (c001) User is Fred ID is (userid001)
2019-09-18 08:14:19.222  D/INFOPRE:     For Conversation SUBJECT AID is (c001) User is Jane ID is (userid003)
2019-09-18 08:14:19.224  D/INFOPRE:     For Conversation SUBJECT XID is (c002) User is Mary ID is (userid002)
2019-09-18 08:14:19.226  D/INFOPRE:     For Conversation SUBJECT XID is (c002) User is Tom ID is (userid004)
2019-09-18 08:14:19.226  D/MAPINFOPRE: Logging Users 
2019-09-18 08:14:19.227  D/USERINFOPRE:     ID is userid001 Name is Fred
2019-09-18 08:14:19.227  D/USERINFOPRE:     ID is userid002 Name is Mary
2019-09-18 08:14:19.227  D/USERINFOPRE:     ID is userid003 Name is Jane
2019-09-18 08:14:19.227  D/USERINFOPRE:     ID is userid004 Name is Tom
2019-09-18 08:14:19.227  D/CONVINFO: Logging Conversations
2019-09-18 08:14:19.228  D/CONVINFOPRE:     ID is c001 Ttitle is SUBJECT A
2019-09-18 08:14:19.228  D/CONVINFOPRE:     ID is c002 Ttitle is SUBJECT X



2019-09-18 08:14:19.233  D/INFOPOST: Logging Conversations via Original Mapping Table 
2019-09-18 08:14:19.236  D/INFOPOST:    For Conversation SUBJECT AID is (c001) User is Harry ID is (userid001)
2019-09-18 08:14:19.239  D/INFOPOST:    For Conversation SUBJECT AID is (c001) User is Jane ID is (userid003)
2019-09-18 08:14:19.241  D/INFOPOST:    For Conversation SUBJECT XID is (c002) User is Gertrude ID is (userid002)
2019-09-18 08:14:19.243  D/INFOPOST:    For Conversation SUBJECT XID is (c002) User is Tom ID is (userid004)
2019-09-18 08:14:19.243  D/MAPINFOPOST: Logging Users 
2019-09-18 08:14:19.244  D/USERINFOPOST:    ID is userid001 Name is Harry
2019-09-18 08:14:19.244  D/USERINFOPOST:    ID is userid002 Name is Gertrude
2019-09-18 08:14:19.244  D/USERINFOPOST:    ID is userid003 Name is Jane
2019-09-18 08:14:19.244  D/USERINFOPOST:    ID is userid004 Name is Tom
2019-09-18 08:14:19.244  D/CONVINFO: Logging Conversations
2019-09-18 08:14:19.245  D/CONVINFOPOST:    ID is c001 Ttitle is SUBJECT A
2019-09-18 08:14:19.245  D/CONVINFOPOST:    ID is c002 Ttitle is SUBJECT X
  • 可以看出,外键子项仍然存在,但详细信息已更新,并且没有新的非预期用户。