So erstellen Sie einen Primärschlüssel als automatische Inkrementierung für Room Persistence lib

192

Ich erstelle eine Entity-Klasse (Room Persistence lib), die ich foodIdals Autoincrement erstellen möchte .

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

Wie kann ich foodIdein Autoincrement-Feld festlegen ?

chandil03
quelle
4
Anstatt 0.toDouble()Sie verwenden können, 0.0deklarieren Sie es als Doppel
RobCo
1
Wie erstellen Sie eine neue Instanz der Lebensmittelklasse? Geben Sie die ID manuell an oder lassen Sie sie leer?
Zookey
2
Ein Hinweis für zukünftige Leser - der Primärschlüssel muss 0 sein, damit Room ihn als nicht gesetzt behandelt. Wenn Sie einen anderen Standardwert verwenden (z. B. -1), generiert Room die ID nicht automatisch.
Martin Melka

Antworten:

370

Sie müssen die autoGenerateEigenschaft verwenden

Ihre Primärschlüsselanmerkung sollte folgendermaßen aussehen:

@PrimaryKey(autoGenerate = true)

Referenz für PrimaryKey .

MatPag
quelle
3
Danke, ich habe nach autoIncrement gesucht, deshalb konnte ich es nicht finden.
Chandil03
Hey @MatPag, was ist, wenn ich zwei Primärschlüssel in einer Tabelle (zusammengesetzte Primärschlüssel) möchte und einer der Primärschlüssel automatisch inkrementiert werden soll? Wie kann ich das erreichen? Können Sie das hier beantworten ?
Priyanka Alachiya
1
@MatPeg Was passiert, wenn ich einen PrimaryKey haben möchte, der selbst generiert wurde und einen, der von REST stammt @Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))?
Murt
@murt Sie benötigen einen zusammengesetzten Primärschlüssel, können aber nicht das tun, was Sie erreichen möchten. Lesen Sie hier
MatPag
Wichtiger Teil der verlinkten Dokumentation:Insert methods treat 0 as not-set while inserting the item.
Micha
123

Sie können @PrimaryKey(autoGenerate = true)wie folgt hinzufügen :

@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
quelle
34
foodIdmuss nicht null sein (kann es aber sein). Man könnte auch Standardwerte verwenden, z. var foodId: Int = 0und die automatische Generierung würde richtig funktionieren.
Michał Baran
8
@ MichałBaran, aus dem Java-Dokument, wenn der Typ ein primitiver Java ist intoder long0 als nullfähig behandelt wird, wenn der Typ Integer oder Long ist, ist null die Nullwert. Da Kotlin Int, wenn nicht nullbar in JVM als primitives int funktioniert, dann haben Sie Recht und var foodId: Int = 0werden arbeiten, aber var foodId: Int? = 0nicht funktionieren, seit Int? wird in JVM als Integer konvertiert. @JMK, wenn Sie es auf 0 setzen, MÜSSEN Sie intaus dem oben genannten Grund ein Nicht-Nullwert machen .
Allan Veloso
2
Sie können auf andere Weise ohne schreiben: val jack = User(name = "Jack", phone= 1)In diesem Fall können Sie 0 aus dem Konstruktor entfernen
user7856586
1
Das Problem, das ich bei diesem Ansatz sehe, besteht darin, dass es sich um eine Datenklasse handelt. Wenn Lebensmittel eine Datenklasse sind (wie im Snippet), werden Lebensmittel für den Vergleich mit equals () verwendet, sodass zwei Lebensmittel mit unterschiedlicher foodId als gleich angesehen werden können. Die Verwendung benannter Argumente mit Standardwerten löst das Problem.
Sotti
1
@AllanVeloso Kannst du erklären, warum foodIdin den Body und nicht in den Konstruktor eingefügt wurde?
Neeraj Sewani
42

hinzufügen @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;
    }

}

beim Speichern von Daten

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

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

Typ 1

Wenn Sie keinen Wert für den Primärschlüssel übergeben, ist dieser standardmäßig 0 oder null.

Typ 2

Geben Sie beim Erstellen des Objekts (mein Fallbenutzerobjekt) null oder null für die ID ein.

Wenn der Feldtyp long oder int ist (oder sein TypeConverter ihn in long oder int konvertiert), behandeln Insert-Methoden 0 beim Einfügen des Elements als nicht gesetzt.

Wenn der Feldtyp Integer oder Long (Object) ist (oder sein TypeConverter ihn in eine Integer oder Long konvertiert), behandeln Insert-Methoden null als nicht gesetzt, während das Element eingefügt wird.

kunal khedkar
quelle
1
Können wir eine benutzerdefinierte ID an Entity übergeben, obwohl diese auf autoGenerate eingestellt ist?
Igor Ganapolsky
2
@Igor Ganapolsky Ja, aber der Eintrag wird mit dieser benutzerdefinierten ID generiert [Auto-Inkrement funktioniert nicht]. Wenn Sie dieselbe ID erneut übergeben, wird die Ausnahme 'EINZIGARTIGE Einschränkung fehlgeschlagen' ausgelöst, sodass Sie immer eine neue ID übergeben oder [0 oder null] und lassen Sie das automatische Inkrementieren für Sie arbeiten.
Kunal Khedkar
3
Warum lässt du den Benutzer die ID überhaupt in den Konstruktor einfügen, wenn du automatisch generieren willst?
Hellcast
In Kotlin können Sie Datenklasse verwenden und schreiben: val jack = User(name = "Jack", phone= 1)In diesem Fall können Sie 0 aus dem Konstruktor entfernen
user7856586
@hellcast Wenn Sie die ID nicht in den Konstruktor aufnehmen (wie ich gerade auf die harte Tour gelernt habe), wird beim Abfragen der Datenbank das ID-Feld nicht zugewiesen (es ist nur das, womit Sie es im Konstruktor initialisieren) Ich gehe davon aus, dass es denselben Konstruktor aufruft, wenn die Felder des Objekts ausgefüllt werden.
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
quelle
4
Während dieses Code-Snippet die Lösung sein kann, hilft das Hinzufügen einer Erklärung wirklich, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage in Zukunft für Leser beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen.
Johan
4
Es gibt viele Antworten wie "Verwenden @PrimaryKey(autoGenerate = true)" - fügt Ihre Antwort diesem Thread etwas Neues hinzu?
Barbansan
ja, es fügt hinzu - es zeigt, wie null das autogenearted Feld
abdeckt
5

Wenn Sie beispielsweise eine usersEntität haben , die Sie speichern möchten, mit Feldern (firstname, lastname , email)und einer automatisch generierten ID, tun Sie dies.

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

Der Raum generiert dann automatisch das idFeld und erhöht es automatisch .

Mayojava
quelle
21
Jedes Mal, wenn wir ein neues Benutzerobjekt erstellen, müssen wir ein ID-Feld übergeben. Kann das vermieden werden?
Aditya Ladwa
10
Ja, @PrimaryKey(autoGenerated = true) val id: Long? = nullaußerhalb des Konstruktors auf den Körper der Klasse setzen
Allan Veloso
1
@Magritte Möchtest du mehr pls ausarbeiten?
Ispam
2
@Ispam In meiner obigen Antwort habe ich gepostet, wie die gesamte Klasse aussehen soll.
Allan Veloso
2
Eigentlich können Sie einfach 0 als ID eingeben. Room generiert automatisch eine ID, wenn Sie die Option @PrimaryKey festgelegt haben.
Romaneso
1

Kommentieren Sie Ihre Entitätsklasse mit dem obigen Code.

In Java

@PrimaryKey(autoGenerate = true)
private int id;

In Kotlin

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

Der Raum generiert dann automatisch das ID-Feld und erhöht es automatisch.

Faxriddin Abdullayev
quelle