Jak zrobić klucz podstawowy jako autoinkrementację dla biblioteki Room Persistence

196

Tworzę jedzenie klasy Entity (Room Persistence lib), w którym chcę zrobić foodIdjako autowzrost.

@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()
}

Jak mogę ustawić foodIdpole autoinkrementacji?

chandil03
źródło
4
Zamiast tego 0.toDouble()możesz użyć 0.0deklaruj jako podwójny
RobCo
2
Jak utworzyć nową instancję klasy Food? Czy podajesz identyfikator ręcznie, czy pozostawiasz go pustym?
Zookey,
3
Uwaga dla przyszłych czytelników - klucz podstawowy musi wynosić 0, aby Room mógł traktować go jako rozbrojony. Jeśli użyjesz innej wartości domyślnej (np. -1), Room nie wygeneruje automatycznie identyfikatora.
Martin Melka

Odpowiedzi:

375

Musisz skorzystać z autoGeneratewłaściwości

Adnotacja klucza podstawowego powinna wyglądać następująco:

@PrimaryKey(autoGenerate = true)

Odwołanie do PrimaryKey .

MatPag
źródło
3
Dzięki, szukałem autoIncrement, dlatego nie mogłem znaleźć.
chandil03
Hej @ MatPag, co jeśli chcę dwa klucze podstawowe w jednej tabeli (klucze podstawowe złożone), a jeden z kluczy podstawowych powinien być automatycznie zwiększany? Jak mogę to osiągnąć? Czy możesz tutaj odpowiedzieć ?
Priyanka Alachiya
1
@MatPeg Co się stanie, jeśli chcę mieć jeden klucz podstawowy, który jest generowany przez siebie i ten, który pochodzi z usługi REST @Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))?
murt
@murt Potrzebujesz złożonego klucza podstawowego, ale nie możesz robić tego, co chcesz osiągnąć. Przeczytaj tutaj
MatPag,
Ważna część powiązanej dokumentacji:Insert methods treat 0 as not-set while inserting the item.
Micha
127

Możesz dodać w @PrimaryKey(autoGenerate = true)ten sposób:

@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()
}
Allan Veloso
źródło
35
foodIdnie musi być zerowy (ale może być). Można również użyć wartości domyślnych np. var foodId: Int = 0i automatyczne generowanie działałoby poprawnie.
Michał Baran
8
@ MichałBaran, z dokumentu java, gdy typ jest pierwotną javą intlub long, 0 jest traktowane jako nullable, gdy typem jest liczba całkowita lub długa, null jest zerowalne. Ponieważ Kotlin Int, gdy niepenulowalna działa w JVM jako prymitywna int, masz rację i var foodId: Int = 0będziesz działać, ale var foodId: Int? = 0nie będzie działać od Int? jest konwertowany w JVM jako liczba całkowita. @JMK, jeśli zrobisz to 0, MUSISZ zrobić niezerową intz wyżej wymienionego powodu.
Allan Veloso,
3
Możesz pisać bez w inny sposób: val jack = User(name = "Jack", phone= 1)W tym przypadku możesz usunąć 0 z konstruktora
7856586
2
@AllanVeloso Czy możesz wyjaśnić, dlaczego foodIdzostał umieszczony w ciele, a nie w konstruktorze?
Neeraj Sewani
2
@ neer17, ponieważ foodId będzie automatycznie generowany przez Room przy wstawianiu, bardziej prawdopodobne, że nie będzie sensu mieć go w konstruktorze.
Allan Veloso
42

Dodaj @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;
    }

}

podczas przechowywania danych

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

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

typ 1

Jeśli nie przekazujesz wartości klucza podstawowego, domyślnie będzie to 0 lub zero.

typ 2

Ustaw wartość zerową lub zerową dla identyfikatora podczas tworzenia obiektu (obiekt użytkownika mojego przypadku)

Jeśli typ pola jest długi lub int (lub jego TypeConverter konwertuje go na long lub int), metody Insert traktują 0 jako nieustawione podczas wstawiania elementu.

Jeśli typ pola to Integer lub Long (Object) (lub jego TypeConverter konwertuje go na Integer lub Long), metody Insert traktują wartość null jako nieustawioną podczas wstawiania elementu.

kunal khedkar
źródło
1
Czy możemy przekazać niestandardowy identyfikator do Entity, nawet jeśli jest on ustawiony na autoGenerate?
IgorGanapolsky
2
@Igor Ganapolsky Tak, ale wpis zostanie wygenerowany przy użyciu tego niestandardowego identyfikatora [automatyczne zwiększanie nie zadziała] A jeśli ponownie przekażesz ten sam identyfikator, wygeneruje wyjątek „Niepowtarzalne ograniczenie UNIQUE”, więc musisz podać zawsze nowy identyfikator lub wprowadzić [0 lub null] i pozwól, aby automatyczne zwiększanie wykonało tę pracę za Ciebie.
kunal khedkar
3
Dlaczego nawet pozwalasz użytkownikowi wstawić identyfikator do konstruktora, jeśli chcesz automatycznie generować?
hellcast
W Kotlin możesz użyć klasy danych i napisać: val jack = User(name = "Jack", phone= 1)W tym przypadku możesz usunąć 0 z konstruktora
7856586
@hellcast Jeśli nie umieścisz identyfikatora w konstruktorze (jak właśnie nauczyłem się na własnej skórze) podczas zapytania do bazy danych, nie przypisze on pola identyfikatora (będzie to tylko to, co zainicjujesz w konstruktorze), ponieważ Zakładam, że wywołuje ten sam konstruktor podczas wypełniania pól obiektu.
Ali Hirani
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,
        "","","","")
}
Om Prakash Sharma
źródło
4
Ten fragment kodu może być rozwiązaniem, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że w przyszłości odpowiadasz na pytanie czytelników, a ci ludzie mogą nie znać przyczyn Twojej sugestii kodu.
Johan
4
Istnieje wiele odpowiedzi typu „użyj @PrimaryKey(autoGenerate = true)” - czy twoja odpowiedź dodaje coś nowego do tego wątku?
barbsan
tak, dodaje - pokazuje, jak null obejmuje pole autogenearted
Marian Paździoch
5

Na przykład, jeśli masz usersencję, którą chcesz przechowywać, wraz z polami (firstname, lastname , email)i chcesz automatycznie wygenerowanego identyfikatora, robisz to.

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

Pokój automatycznie wygeneruje i automatycznie zwiększy idpole.

Mayojava
źródło
22
Za każdym razem, gdy tworzymy nowy obiekt Users, będziemy musieli przekazać pole identyfikatora. Czy można tego uniknąć?
Aditya Ladwa
11
Tak, umieść @PrimaryKey(autoGenerated = true) val id: Long? = nullpoza konstruktorem, na ciele klasy
Allan Veloso
1
@Magritte Chcesz opracować więcej informacji?
Ispam
2
@Spam W powyższej odpowiedzi podałem, jak powinna wyglądać cała klasa.
Allan Veloso
3
W rzeczywistości możesz po prostu wpisać 0 jako identyfikator. Pokój automatycznie wygeneruje identyfikator, jeśli ustawiłeś opcję @PrimaryKey.
romaneso,
1

Opisz swoją klasę Entity za pomocą powyższego kodu.

W Javie

@PrimaryKey(autoGenerate = true)
private int id;

W Kotlinie

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

Pokój automatycznie wygeneruje i automatycznie zwiększy pole identyfikatora.

Faxriddin Abdullayev
źródło