Como criar a chave primária como incremento automático para a lib de persistência de sala

192

Estou criando uma classe Entity (Room Persistence lib) Food, onde quero fazer foodIdcomo incremento automático.

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

Como posso definir foodIdum campo de incremento automático?

chandil03
fonte
4
Em vez de 0.toDouble()você pode usar 0.0, declare-o como um duplo
RobCo
2
Como você cria uma nova instância da classe Food? Você especifica o ID manualmente ou o deixa em branco?
Zookey
2
Uma observação para futuros leitores - a chave primária deve ser 0 para que o Room a trate como não definida. Se você usar qualquer outro valor padrão (por exemplo, -1), o Room não gerará automaticamente o ID.
Martin Melka 5/04

Respostas:

370

Você precisa usar a autoGeneratepropriedade

Sua anotação de chave primária deve ser assim:

@PrimaryKey(autoGenerate = true)

Referência para PrimaryKey .

MatPag
fonte
3
Obrigado, eu estava procurando por autoIncrement, é por isso que não foi possível encontrar.
chandil03
Ei, @ MatPag, e se eu quiser duas chaves primárias em uma tabela (chaves primárias compostas) e uma das chaves primárias deve ser incrementada automaticamente? Como posso conseguir isso? Você pode responder isso aqui ?
Priyanka Alachiya
1
@ MatPeg E se eu quiser que uma PrimaryKey seja gerada automaticamente e que seja proveniente do REST @Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))?
murt
@urt Você precisa de uma chave primária composta, mas não pode fazer o que deseja alcançar. Leia aqui
MatPag
Parte importante da documentação vinculada:Insert methods treat 0 as not-set while inserting the item.
Micha
123

Você pode adicionar @PrimaryKey(autoGenerate = true)assim:

@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
fonte
34
foodIdnão precisa ser nulo (mas pode ser). Pode-se também usar valores padrão, por exemplo. var foodId: Int = 0e a geração automática funcionaria corretamente.
Michał Baran
8
@ MichałBaran, do java doc, quando o tipo é um java primitivo intou long, 0 é tratado como nulo, quando o tipo é Inteiro ou Longo, nulo é anulável. Como o Kotlin Int, quando não anulável, funciona na JVM como int primitivo, você está certo e var foodId: Int = 0funcionará, mas var foodId: Int? = 0não funcionará desde o Int? é convertido na JVM como Inteiro. @JMK, se você o fizer 0, terá que criar um valor não nulo intpelo motivo acima mencionado.
Allan Veloso
2
Você pode escrever sem de outra maneira: val jack = User(name = "Jack", phone= 1)Nesse caso, você pode remover 0 do construtor
user7856586
1
O problema que vejo com essa abordagem é o fato de ser uma classe de dados. Quando Food é uma classe de dados (como no trecho), o alimento é usado para a comparação igual (), portanto, dois alimentos com ID de alimento diferente podem ser considerados iguais. O uso de argumentos nomeados com valores padrão resolverá o problema.
Sotti
1
@AllanVeloso Você pode explicar por que foodIdfoi colocado no corpo e não no construtor?
Neeraj Sewani 18/10/19
42

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

}

enquanto armazena dados

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

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

tipo 1

Se você não estiver passando valor para a chave primária, por padrão, será 0 ou nulo.

tipo 2

Coloque nulo ou zero para o ID durante a criação do objeto (objeto de usuário do meu caso)

Se o tipo de campo for longo ou int (ou seu TypeConverter o converter em longo ou int), os métodos Insert tratam 0 como não definido durante a inserção do item.

Se o tipo do campo for Inteiro ou Longo (Objeto) (ou seu TypeConverter o converte em Inteiro ou Longo), os métodos Insert tratam nulo como não definido durante a inserção do item.

kunal khedkar
fonte
1
Podemos passar o ID personalizado para a Entidade, mesmo que esteja definido como autoGenerate?
IgorGanapolsky
2
@Igor Ganapolsky Sim, mas a entrada será gerada com esse ID personalizado [o incremento automático não funcionará]. E se você passar o mesmo ID novamente, lançará a exceção 'Falha na restrição UNIQUE'; portanto, você deve passar sempre um novo ID ou torná-lo [0 ou null] e deixe que o incremento automático faça esse trabalho por você.
Kunal khedkar
3
Por que você está deixando o usuário colocar o ID no construtor se deseja gerar automaticamente?
Hellcast
No Kotlin, você pode usar a classe de dados e escrever: val jack = User(name = "Jack", phone= 1)Nesse caso, você pode remover 0 do construtor
user7856586
@ hellcast Se você não incluir o id no construtor (como acabei de aprender da maneira mais difícil), quando você consultar o banco de dados, ele não atribuirá o campo id (será apenas o que você inicializar no construtor), pois Suponho que ele chama o mesmo construtor ao preencher os campos do objeto.
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
fonte
4
Embora esse snippet de código possa ser a solução, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se de que você está respondendo à pergunta dos leitores no futuro e essas pessoas podem não saber os motivos da sua sugestão de código.
9609 Johan
4
Existem muitas respostas como "use @PrimaryKey(autoGenerate = true)" - sua resposta adiciona algo novo a esse tópico?
barbsan
sim, acrescenta - apresenta como o nulo cobre o campo autogenearted
Marian Paździoch
5

Por exemplo, se você possui uma usersentidade que deseja armazenar, com campos (firstname, lastname , email)e deseja um ID gerado automaticamente, faça isso.

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

A sala gerará automaticamente e incrementará automaticamente o idcampo.

mayojava
fonte
21
Toda vez que criamos um novo objeto Usuários, precisamos passar um campo de identificação. Isso pode ser evitado?
Aditya Ladwa #
10
Sim, coloque @PrimaryKey(autoGenerated = true) val id: Long? = nullfora do construtor, no corpo da classe
Allan Veloso
1
@Magritte Cuidados para elaborar mais pls?
Ispam
2
@Ispam Na minha resposta acima, eu postei como deveria ser a classe completa.
Allan Veloso
2
Na verdade, você pode simplesmente colocar 0 como ID. O quarto gerará um ID automaticamente se você tiver definido a opção @PrimaryKey.
11789 romaneso
1

Anote sua classe de entidade com o código acima.

Em Java

@PrimaryKey(autoGenerate = true)
private int id;

Na cidade Kotlin

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

A sala gerará automaticamente e incrementará automaticamente o campo de identificação.

Faxriddin Abdullayev
fonte