Cách tạo khóa chính làm tự động cho lib Persistence lib


192

Tôi đang tạo một lớp Thực phẩm (Room Persistence lib), nơi tôi muốn thực hiện foodIddưới dạng tự động.

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

Làm thế nào tôi có thể thiết lập foodIdmột trường tự động?


4
Thay vì 0.toDouble()bạn có thể sử dụng, 0.0hãy khai báo là gấp đôi
RobCo

1
Làm thế nào bạn tạo một thể hiện mới của lớp Food? Bạn có chỉ định ID thủ công hoặc bạn để trống?
Zookey

2
Một lưu ý cho người đọc trong tương lai - khóa chính phải là 0 đối với Room để coi nó là không đặt. Nếu bạn sử dụng bất kỳ giá trị mặc định nào khác (ví dụ -1), Room sẽ không tự động tạo id.
Martin Melka

Câu trả lời:


370

Bạn cần sử dụng autoGeneratetài sản

Chú thích khóa chính của bạn nên như thế này:

@PrimaryKey(autoGenerate = true)

Tài liệu tham khảo cho khóa chính .


3
Cảm ơn, tôi đã tìm kiếm autoIncrement, đó là lý do tại sao không thể tìm thấy.
chandil03

Xin chào @MatPag nếu tôi muốn hai khóa Chính trong một bảng (Khóa chính tổng hợp) và một trong các khóa chính sẽ được tự động tăng? Làm thế nào tôi có thể đạt được điều đó? Bạn có thể trả lời điều này ở đây không?
Priyanka Alachiya

1
@MatPeg Điều gì trong trường hợp nếu tôi muốn có một Chính khóa, thì nó tự tạo và một từ đến từ REST @Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))?
murt

@murt Bạn cần một khóa chính tổng hợp, nhưng bạn không thể làm những gì bạn muốn đạt được. Đọc ở đây
MatPag

Phần quan trọng của tài liệu được liên kết:Insert methods treat 0 as not-set while inserting the item.
Micha

123

Bạn có thể thêm @PrimaryKey(autoGenerate = true)như thế này:

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

34
foodIdkhông cần phải là null (nhưng nó có thể). Người ta cũng có thể sử dụng các giá trị mặc định, ví dụ. var foodId: Int = 0và autogenerate sẽ hoạt động đúng.
Michał Baran

8
@ MichałBaran, từ tài liệu java, khi loại là java nguyên thủy inthoặc long, 0 được coi là null-null, khi loại là Integer hoặc Long, null là nullable. Vì Kotlin Int khi không thể null hoạt động trong JVM dưới dạng int nguyên thủy, nên bạn đã đúng và var foodId: Int = 0sẽ hoạt động, nhưng var foodId: Int? = 0sẽ không hoạt động kể từ Int? được chuyển đổi trong JVM dưới dạng Integer. @JMK, nếu bạn làm cho nó 0, bạn PHẢI làm cho một giá trị không thể rỗng intvì lý do đã nói ở trên.
Allan Veloso

2
Bạn có thể viết mà không cần theo cách khác: val jack = User(name = "Jack", phone= 1)Trong trường hợp này, bạn có thể xóa 0 khỏi hàm tạo
user7856586 16/11/18

1
Vấn đề tôi thấy với cách tiếp cận này là về mặt nó là một lớp dữ liệu. Khi Thực phẩm là một lớp dữ liệu (như trong đoạn trích), thực phẩm được sử dụng để so sánh bằng (), vì vậy hai loại thực phẩm có thực phẩm khác nhau có thể được coi là bằng nhau. Sử dụng các đối số được đặt tên với các giá trị mặc định sẽ giải quyết vấn đề.
Sotti

1
@ ALLanVeloso Bạn có thể giải thích tại sao foodIdđược đưa vào cơ thể mà không phải trong nhà xây dựng?
Neeraj Sewani

42

thêm vào @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;
    }

}

trong khi lưu trữ dữ liệu

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

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

loại 1

Nếu bạn không truyền giá trị cho khóa chính, theo mặc định, nó sẽ là 0 hoặc null.

loại 2

Đặt null hoặc 0 cho id trong khi tạo đối tượng (đối tượng người dùng trường hợp của tôi)

Nếu loại trường dài hoặc int (hoặc TypeConverter của nó chuyển đổi thành dài hoặc int), phương thức Chèn xử lý 0 là không được đặt trong khi chèn mục.

Nếu loại của trường là Integer hoặc Long (Object) (hoặc TypeConverter của nó chuyển đổi nó thành Integer hoặc Long), các phương thức Chèn xử lý null là không được đặt trong khi chèn mục.


1
Chúng tôi có thể chuyển id tùy chỉnh cho Thực thể không, mặc dù nó được đặt thành autoGenerate?
IgorGanapolsky

2
.... null] và để tự động tăng làm công việc này cho bạn.
kunal khedkar

3
Tại sao bạn thậm chí cho phép người dùng đặt id vào hàm tạo nếu bạn muốn tự động tạo?
hellcast

Trong Kotlin, bạn có thể sử dụng lớp dữ liệu và viết: val jack = User(name = "Jack", phone= 1)Trong trường hợp này, bạn có thể xóa 0 khỏi hàm tạo
user7856586

@hellcast Nếu bạn không bao gồm id trong hàm tạo (vì tôi vừa học một cách khó khăn) khi bạn truy vấn DB, nó sẽ không gán trường id (nó sẽ chỉ là bất cứ thứ gì bạn khởi tạo nó trong hàm tạo) Tôi giả sử nó gọi cùng một hàm tạo khi điền vào các trường của đối tượng.
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,
        "","","","")
}

4
Mặc dù đoạn mã này có thể là giải pháp, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
Johan

4
Có nhiều câu trả lời như "sử dụng @PrimaryKey(autoGenerate = true)" - câu trả lời của bạn có thêm điều gì mới cho chủ đề này không?
barbsan

vâng, nó cho biết thêm - nó trình bày cách null bao phủ trường tự động
Marian Paździoch

5

Ví dụ: nếu bạn có một usersthực thể bạn muốn lưu trữ, với các trường (firstname, lastname , email)và bạn muốn id được tạo tự động, bạn làm điều này.

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

Phòng sau đó sẽ tự động phát và tự động tăng idtrường.


21
Mỗi khi chúng ta tạo một đối tượng Người dùng mới, chúng ta sẽ cần phải vượt qua một trường id. Điều này có thể tránh được không?
Aditya Ladwa

10
Có, đặt @PrimaryKey(autoGenerated = true) val id: Long? = nullbên ngoài nhà xây dựng, trên cơ thể của lớp
Allan Veloso

1
@Magritte Chăm sóc để giải thích thêm xin vui lòng?
Ispam

2
@Ispam Trong câu trả lời của tôi ở trên, tôi đã đăng bài hoàn chỉnh như thế nào.
Allan Veloso

2
Trên thực tế, bạn có thể chỉ cần đặt 0 làm ID. Room sẽ tự động tạo ID nếu bạn đã đặt tùy chọn @PrimaryKey.
romaneso

1

Chú thích lớp Thực thể của bạn với mã ở trên.

Trong Java

@PrimaryKey(autoGenerate = true)
private int id;

Ở Kotlin

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

Phòng sau đó sẽ tự động phát và tự động tăng trường id.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.