Як зробити первинний ключ як автоматичне посилення для кімнати


196

Я створюю їжу класу Entity (Room Persistence lib), де я хочу зробити 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поле для автоматичного збільшення?


4
Замість цього 0.toDouble()ви можете використовувати 0.0, оголосити це як подвійне
RobCo

2
Як ви створюєте новий екземпляр класу Food? Ви вказуєте ідентифікатор вручну або залишаєте його порожнім?
Zookey

3
Примітка для майбутніх читачів - первинний ключ повинен бути 0 для кімнати, щоб вважати це невстановленим. Якщо ви використовуєте будь-яке інше значення за замовчуванням (наприклад, -1), Room не автоматично створить ідентифікатор.
Мартін Мелька

Відповіді:


375

Вам потрібно використовувати autoGenerateмайно

Ваша основна примітка щодо ключових слів повинна бути такою:

@PrimaryKey(autoGenerate = true)

Довідка для PrimaryKey .


3
Дякую, я шукав автоматичне збільшення, ось чому не вдалося знайти.
chandil03

Привіт @MatPag, що робити, якщо я хочу два первинні ключі в одній таблиці (складені первинні ключі) та один із первинних ключів слід автоматично наростити? Як я можу цього досягти? Ви можете відповісти на це тут ?
Приянка Алахія

1
@MatPeg Що робити у випадку, якщо я хочу мати один PrimaryKey, який створюється самостійно, а той, який надходить з REST @Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))?
мурти

@murt Вам потрібен складений первинний ключ, але ви не можете робити того, чого хочете досягти. Читайте тут
MatPag

Важлива частина пов’язаної документації:Insert methods treat 0 as not-set while inserting the item.
Міха

127

Ви можете додати @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()
}

35
foodIdне має бути нульовим (але це може бути). Можна також використовувати значення за замовчуванням, наприклад. var foodId: Int = 0і автогенератор працював би належним чином.
Міхал Баран

8
@ MichałBaran, від java doc, коли тип є примітивним java intабо long0 вважається нульовим, коли тип Integer або Long, null є нульовим. Оскільки Kotlin Int, коли нерегульований працює в JVM як примітивний int, то ви маєте рацію і var foodId: Int = 0будете працювати, але var foodId: Int? = 0не працюватимете з Int? перетворюється в JVM як цілий. @JMK, якщо ви робите 0, ви повинні зробити нерегульовані intз причини, згаданої вище.
Allan Veloso

3
Ви можете писати без іншого способу: val jack = User(name = "Jack", phone= 1)у цьому випадку ви можете видалити 0 з конструктора
user7856586

2
@AllanVeloso Чи можете ви пояснити, чому foodIdбуло поставлено в тіло, а не в конструктор?
Neeraj Sewani

2
@ neer17, оскільки foodId буде автоматично генерований Room при вставці, швидше за все, не буде користі, щоб він був у конструкторі.
Allan Veloso

42

додати @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 або недійсне.

тип-2

Поставте null або zero для ідентифікатора під час створення об’єкта (мій об'єкт user user)

Якщо тип поля довгий або int (або його TypeConverter перетворює його в довгий або int), Insert методи вважають 0 не встановленим під час вставки елемента.

Якщо тип поля "Цілий" або "довгий" (об'єкт) (або його TypeConverter перетворює його в цілий чи довгий), при вставці елемента методами "Вставлення" трактуються як "не встановлені".


1
Чи можемо ми передати спеціальний ідентифікатор Entity, навіть якщо він встановлений для autoGenerate?
ІгорГанапольський

2
@Igor Ganapolsky Так, але запис буде генеровано за допомогою цього спеціального ідентифікатора [автоматичне збільшення не буде працювати] І якщо ви повторно передасте той самий ідентифікатор, він викине виняток "UNIQUE обмеження не вдалося", тому вам потрібно завжди передавати новий ідентифікатор або вносити його [0 або null] і дозвольте автоматичному збільшенню зробити це за вас.
кунальний хедкар

3
Чому ви навіть дозволяєте користувачеві вводити ідентифікатор у конструктор, якщо ви хочете автогенерувати?
пекло

У Котліні ви можете використовувати клас даних та писати: 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,
        "","","","")
}

4
Хоча цей фрагмент коду може бути вирішенням, включаючи пояснення, справді допомагає покращити якість вашої публікації. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду.
Йоган

4
Є багато відповідей на кшталт "використання @PrimaryKey(autoGenerate = true)" - чи додає ваша відповідь щось нове в цю нитку?
барбсан

так, це додає - в ньому представлено, як нуль покриває автогенеровані поля
Маріан Падьоч

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
)

Кімната потім автоматично генерує та автоматично збільшує idполе.


22
Кожного разу, коли ми створюємо новий об’єкт Користувачі, нам потрібно буде пройти поле ідентифікатора. Чи можна цього уникнути?
Aditya Ladwa

11
Так, поставлений @PrimaryKey(autoGenerated = true) val id: Long? = nullпоза конструктором, на корпусі класу
Аллан Велосо

1
@Magritte Care розробити більше PLS?
Іспам

2
@Ispam У своїй відповіді вище я розмістив, як повинен виглядати повний клас.
Аллан Велосо

3
Насправді ви можете просто поставити 0 як ідентифікатор. Кімната автоматично генерує ідентифікатор, якщо ви встановили параметр @PrimaryKey.
romaneso

1

Повідомте свій клас Entity за допомогою наведеного вище коду.

На Java

@PrimaryKey(autoGenerate = true)
private int id;

У Котліні

@PrimaryKey(autoGenerate = true)
var id: Int;

Потім номер автоматично автогенерується та автоматично збільшується поле id.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.