Как сделать первичный ключ как автоинкремент для библиотеки Room Persistence

209

Я создаю Entity ( Room Persistence Library ) класса Food, где хочу сделать foodIdавтоинкремент.

@Entity
class Food(var foodName: String, var foodDesc: String, var protein: Double, var carbs: Double, var fat: Double)
{
    @PrimaryKey
    var foodId: Int = 0
    var calories: Double = 0.toDouble()
}

Как установить foodIdполе автоинкремента?

chandil03
источник
4
Вместо того, 0.toDouble()чтобы использовать 0.0, объявите это как двойное
RobCo
2
Как вы создаете новый экземпляр класса Food? ID указываете вручную или оставляете пустым?
Zookey
6
Примечание для будущих читателей - первичный ключ должен быть равен 0, чтобы Room считал его незаданным. Если вы используете любое другое значение по умолчанию (например, -1), Room не будет автоматически генерировать идентификатор.
Мартин Мелка,

Ответы:

399

Вам нужно использовать autoGenerateнедвижимость

Ваша аннотация первичного ключа должна быть такой:

@PrimaryKey(autoGenerate = true)

Ссылка на PrimaryKey .

MatPag
источник
3
Спасибо, я искал autoIncrement, поэтому не смог найти.
chandil03
Привет, @MatPag, а что, если я хочу, чтобы два первичных ключа в одной таблице (составные первичные ключи), и один из первичных ключей должен быть автоматически увеличен? Как я могу этого добиться? Вы можете здесь ответить ?
Приянка Алачия
1
@MatPeg Что делать в случае, если я хочу, чтобы один PrimaryKey был самогенерирован, а другой - из REST @Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))?
murt
@murt Вам нужен составной первичный ключ, но вы не можете делать то, что хотите. Читайте здесь
MatPag
Важная часть связанной документации:Insert methods treat 0 as not-set while inserting the item.
Micha
138

Вы можете добавить @PrimaryKey(autoGenerate = true)вот так:

@Entity
data class Food(
        var foodName: String, 
        var foodDesc: String, 
        var protein: Double, 
        var carbs: Double, 
        var fat: Double
){
    @PrimaryKey(autoGenerate = true)
    var foodId: Int = 0 // or foodId: Int? = null
    var calories: Double = 0.toDouble()
}
Аллан Велосо
источник
39
foodIdне обязательно должно быть нулевым (но может быть). Можно также использовать значения по умолчанию, например. var foodId: Int = 0и автогенерация будет работать правильно.
Michał Baran
9
@ MichałBaran, из java-документа, когда тип является примитивным java intили long0 рассматривается как допускающий значение NULL, когда тип Integer или Long, null является допускающим значение NULL. Поскольку Kotlin Int, когда не допускает значения NULL, работает в JVM как примитивный int, то вы правы и var foodId: Int = 0будете работать, но var foodId: Int? = 0не будет работать, поскольку Int? преобразуется в JVM как целое число. @JMK, если вы сделаете это 0, вы ДОЛЖНЫ сделать значение, не допускающее значение NULL, intпо вышеупомянутой причине.
Аллан Велосо,
3
Вы можете написать без него другим способом: val jack = User(name = "Jack", phone= 1)в этом случае вы можете удалить 0 из конструктора
user7856586
2
@AllanVeloso Вы можете объяснить, почему foodIdбыло помещено в тело, а не в конструктор?
Neeraj Sewani
3
@ neer17, так как foodId будет автоматически сгенерирован Room при вставке, более вероятно, что он будет бесполезен в конструкторе.
Аллан Велосо
46

Добавить @PrimaryKey(autoGenerate = true)

@Entity
public class User {

    @PrimaryKey(autoGenerate = true)
    private int id;

    @ColumnInfo(name = "full_name")
    private String name;

    @ColumnInfo(name = "phone")
    private String phone;

    public User(){
    }

    //type-1
    public User(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

    //type-2
    public User(int id, String name, String phone) {
        this.id = id;
        this.name = name;
        this.phone = phone;
    }

}

при хранении данных

 //type-1
 db.userDao().InsertAll(new User(sName,sPhone)); 

 //type-2
 db.userDao().InsertAll(new User(0,sName,sPhone)); 

Тип 1

Если вы не передаете значение для первичного ключа, по умолчанию оно равно 0 или null.

тип-2

Поместите ноль или ноль для идентификатора при создании объекта (мой пользовательский объект)

Если тип поля long или int (или его TypeConverter преобразует его в long или int), методы Insert обрабатывают 0 как не установленное при вставке элемента.

Если тип поля - Integer или Long (Object) (или его TypeConverter преобразует его в Integer или Long), методы Insert обрабатывают null как неустановленное при вставке элемента.

кунал хедкар
источник
1
Можем ли мы передать пользовательский идентификатор Entity, даже если он настроен на autoGenerate?
Игорь Ганапольский
2
@Igor Ganapolsky Да, но запись будет генерироваться с этим пользовательским идентификатором [автоинкремент не будет работать] И если вы снова передадите тот же идентификатор, он выдаст исключение «UNIQUE constraint failed», поэтому вам нужно всегда передавать новый идентификатор или сделать его [0 или null] и пусть автоинкремент сделает эту работу за вас.
кунал хедкар
3
Почему вы даже позволяете пользователю помещать идентификатор в конструктор, если вы хотите автоматически сгенерировать?
Hellcast
В Kotlin вы можете использовать класс данных и написать: val jack = User(name = "Jack", phone= 1)В этом случае вы можете удалить 0 из конструктора
user7856586
@hellcast Если вы не включаете идентификатор в конструктор (как я только что узнал на собственном опыте), когда вы запрашиваете БД, он не будет назначать поле идентификатора (это будет просто то, что вы инициализируете в конструкторе), поскольку Я предполагаю, что он вызывает тот же конструктор при заполнении полей объекта.
Али Хирани
6
@Entity(tableName = "user")
data class User(

@PrimaryKey(autoGenerate = true)  var id: Int?,
       var name: String,
       var dob: String,
       var address: String,
       var gender: String
)
{
    constructor():this(null,
        "","","","")
}
Ом Пракаш Шарма
источник
5
Хотя этот фрагмент кода может быть решением, включение объяснения действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода.
Johan
4
Есть много ответов типа «использовать @PrimaryKey(autoGenerate = true)» - добавляет ли ваш ответ что-нибудь новое в эту ветку?
barbsan
1
да, он добавляет - он показывает, как null покрывает поле с
автогеном
5

Например, если у вас есть usersобъект, который вы хотите сохранить, с полями (firstname, lastname , email)и вам нужен автоматически сгенерированный идентификатор, вы делаете это.

@Entity(tableName = "users")
data class Users(
   @PrimaryKey(autoGenerate = true)
   val id: Long,
   val firstname: String,
   val lastname: String,
   val email: String
)

Затем Room автоматически сгенерирует и автоматически увеличит значение idполя.

Mayojava
источник
22
Каждый раз, когда мы создаем новый объект Users, нам нужно будет передать поле id. Можно ли этого избежать?
Адитья Ладва,
12
Да, вынесен @PrimaryKey(autoGenerated = true) val id: Long? = nullза пределы конструктора, на тело класса
Аллан Велосо
1
@Magritte Care, пожалуйста, расскажите подробнее?
Ispam
2
@Ispam В моем ответе выше я опубликовал, как должен выглядеть весь класс.
Аллан Велосо
3
Фактически, вы можете просто указать 0 как ID. Room автоматически сгенерирует идентификатор, если вы установили параметр @PrimaryKey.
romaneso
5

Это невероятно после такого количества ответов, но в конце концов я сделал это немного иначе. Мне не нравится, что первичный ключ допускает значение NULL, я хочу, чтобы он был первым аргументом, а также хочу вставить его без его определения, а также не должен быть var.

@Entity(tableName = "employments")
data class Employment(
    @PrimaryKey(autoGenerate = true) val id: Long,
    @ColumnInfo(name = "code") val code: String,
    @ColumnInfo(name = "title") override val name: String
){
    constructor(code: String, name: String) : this(0, code, name)
}
Ренетик
источник
2

Это работает для меня:

@Entity(tableName = "note_table")
data class Note(
    @ColumnInfo(name="title") var title: String,
    @ColumnInfo(name="description") var description: String = "",
    @ColumnInfo(name="priority") var priority: Int,
    @PrimaryKey(autoGenerate = true) var id: Int = 0//last so that we don't have to pass an ID value or named arguments
)

Обратите внимание, что идентификатор является последним, чтобы избежать использования именованных аргументов при создании объекта перед его вставкой в ​​Room. После того, как он был добавлен в комнату, используйте идентификатор при обновлении объекта.

Крис Спраг
источник
1

Аннотируйте свой класс Entity с помощью кода ниже.

В Java:

@PrimaryKey(autoGenerate = true)
private int id;

В Котлине:

@PrimaryKey(autoGenerate = true)
var id: Int

Затем Room автоматически сгенерирует и автоматически увеличит значение поля id.

Факсриддин Абдуллаев
источник