Добавить уникальное ограничение в базе данных комнаты в несколько столбцов

У меня есть одна сущность в комнате

@Entity(foreignKeys ={
        @ForeignKey(entity = Label.class, parentColumns = "_id", childColumns = "labelId", onDelete = CASCADE),
        @ForeignKey(entity = Task.class, parentColumns = "_id", childColumns = "taskId", onDelete = CASCADE)
})
public class LabelOfTask extends Data{
    @ColumnInfo(name = "labelId")
    private Integer labelId;
    @ColumnInfo(name = "taskId")
    private Integer taskId;
}

Синтаксис SQL этого объекта, как показано ниже

CREATE TABLE `LabelOfTask` (
    `_id` INTEGER PRIMARY KEY AUTOINCREMENT,
     `labelId` INTEGER,
     `taskId` INTEGER,
     FOREIGN KEY(`labelId`) REFERENCES `Label`(`_id`) ON UPDATE NO ACTION ON DELETE CASCADE ,
     FOREIGN KEY(`taskId`) REFERENCES `Task`(`_id`) ON UPDATE NO ACTION ON DELETE CASCADE
 );

но какое изменение или аннотацию мне нужно добавить в класс сущности, если я хочу добавить ограничение ниже к автоматически сгенерированной схеме sql таблицы

unique (labelId, taskId)

В конечном счете, я хочу сделать комбинацию labelId и taskId уникальной в таблице (или объекте комнаты), используя библиотеку комнаты.

5 ответов

Решение

Простое УНИКАЛЬНОЕ ограничение для столбца, кроме как через индекс, не поддерживается.

Вы можете применить это свойство уникальности, установив для уникального свойства аннотации @Index значение true. Следующий пример кода не позволяет таблице иметь две строки, содержащие одинаковый набор значений для столбцов firstName и lastName:

@Entity(indices = {@Index(value = {"first_name", "last_name"},
        unique = true)})
class User {
    @PrimaryKey
    public int id;

    @ColumnInfo(name = "first_name")
    public String firstName;

    @ColumnInfo(name = "last_name")
    public String lastName;

    @Ignore
    Bitmap picture;
}

В вашем коде вы можете сделать следующие изменения, чтобы иметь уникальные ограничения

@Entity(foreignKeys ={
        @ForeignKey(entity = Label.class, parentColumns = "_id", childColumns = "labelId", onDelete = CASCADE),
        @ForeignKey(entity = Task.class, parentColumns = "_id", childColumns = "taskId", onDelete = CASCADE)},
        indices = {@Index(value = {"labelId", "taskId"},
                unique = true)}
)
public class LabelOfTask extends Data{
    @ColumnInfo(name = "labelId")
    private Integer labelId;
    @ColumnInfo(name = "taskId")
    private Integer taskId;
}

Если вам интересно сделать один столбец уникальным, нужно всего лишь написать

@Entity(indices = {@Index(value = "name", unique = true)})

Для одного столбца Уникальность

@Entity(indices = {@Index(value = {"first_name"},unique = true)})

Для уникальности нескольких столбцов

@Entity(indices = {@Index(value = {"first_name", "last_name"},unique = true)}) 

Не могу комментировать, поэтому просто добавлю сюда. При ручной миграции вашей базы данных Room DB для добавления индекса с помощью операторов SQL ваше имя индекса, чтобы оно могло соответствовать аннотации в таблице, должно иметь формат:

      ...
database.execSQL("CREATE UNIQUE INDEX index_tableName_columnName ON tableName (columnName)")
...

Не уверен, насколько длинными могут быть имена индексов, поэтому не уверен, как это выглядит с индексами с несколькими столбцами.

Вы также можете добиться уникальности нескольких столбцов с помощью составного первичного ключа (объект уникально идентифицируется комбинацией нескольких столбцов).

      @Entity(primaryKeys = ["firstName", "lastName"])
data class User(
    val firstName: String?,
    val lastName: String?
)

См. официальную документацию

Обратите внимание, что в этом случае вы не можете использовать автоматически созданное приращение идентификатора, SQLite это не поддерживает .

Другие вопросы по тегам