Android Room FOREIGN KEY constraint failed Android Room FOREIGN KEY constraint failed sqlite sqlite

Android Room FOREIGN KEY constraint failed


I got this to work, but not using int primary keys. I'm not a huge fan of those for this sort of ORM scenario, just because of these sorts of problems.

So, here's a self-referential Category class that uses a UUID for its primary key:

/*** Copyright (c) 2017 CommonsWare, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain  a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */package com.commonsware.android.room.dao;import android.arch.persistence.room.Entity;import android.arch.persistence.room.ForeignKey;import android.arch.persistence.room.Ignore;import android.arch.persistence.room.Index;import android.arch.persistence.room.PrimaryKey;import java.util.UUID;import static android.arch.persistence.room.ForeignKey.CASCADE;@Entity(  tableName="categories",  foreignKeys=@ForeignKey(    entity=Category.class,    parentColumns="id",    childColumns="parentId",    onDelete=CASCADE),  indices=@Index(value="parentId"))public class Category {  @PrimaryKey  public final String id;  public final String title;  public final String parentId;  @Ignore  public Category(String title) {    this(title, null);  }  @Ignore  public Category(String title, String parentId) {    this(UUID.randomUUID().toString(), title, parentId);  }  public Category(String id, String title, String parentId) {    this.id=id;    this.title=title;    this.parentId=parentId;  }}

Now you can have DAO methods like:

@Query("SELECT * FROM categories WHERE parentId IS NULL")Category findRootCategory();@Query("SELECT * FROM categories WHERE parentId=:parentId")List<Category> findChildCategories(String parentId);


It took me a loong time to figure out that having a parentColumns element which is an autogenerated primary key does not seem to be allowed at all, even if it is a uuid using a Kotlin data class with a default value like this:

MyClass{    //Don't do this    @PrimaryKey(autoGenerate = true)    var uuid: String = UUID.randomUUID()}

Always make sure the parent column is specified directly by you.