I'm designing a Database that would be implemented in Android using Room, after reading the docs I found that there is no recomendations about using Int or Long as primary keys.
In some places they define entities with int primary keys:
@Entity
data class User(
@PrimaryKey var id: Int,
var firstName: String?,
var lastName: String?
)
But in other place it says that if you want to get the ID of the last row inserted "insert" method return a long.
@Dao
interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertUsers(vararg users: User)
@Insert
fun insertBothUsers(user1: User, user2: User)
@Insert
fun insertUsersAndFriends(user: User, friends: List<User>)
}
If the @Insert method receives only 1 parameter, it can return a long, which is the new rowId for the inserted item. If the parameter is an array or a collection, it should return long[] or List instead.
So, The primary keys in room should be Int or Long?; Are there best practices about choosing one type over the other?
You could change primary key to bigint, bigint (whole number) data from -2^63 (-9,223,372,036,854,775,808) through 2^63-1 (9,223,372,036,854,775,807). Storage size is 8 bytes.
A Room entity includes fields for each column in the corresponding table in the database, including one or more columns that comprise the primary key. The following code is an example of a simple entity that defines a User table with columns for ID, first name, and last name: Kotlin Java.
implements Annotation. android.arch.persistence.room.PrimaryKey. Marks a field in an Entity as the primary key. If you would like to define a composite primary key, you should use primaryKeys() method. Each Entity must declare a primary key unless one of its super classes declares a primary key.
Room is one of the Jetpack Architecture Components in Android. This provides an abstract layer over the SQLite Database to save and perform the operations on persistent data locally.
Both of these types will map to an INTEGER
in the underlying SQLite database.
For example, with a class like this:
@Entity
data class Test(@PrimaryKey val i: Int, val l: Long)
You'd get a SQLite table defined with this query:
CREATE TABLE IF NOT EXISTS `Test` (`i` INTEGER NOT NULL, `l` INTEGER NOT NULL, PRIMARY KEY(`i`))
So you can use whichever one you'll need the magnitude of in your code. If you do decide to use an Int
for some reason and you run out of values, you can even change it to a Long
without having to migrate your database later on.
As for this INTEGER
type, as per the SQLite documentation:
The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.
Both is fine. On mobile (and most of the time in general) Int
should be sufficient (it will also save you 4 bytes over Long
).
Why? Using an Int
you could store over 2 billion records (2_000_000_000). So you could store a record of around 1/4
of all the humans living on earth. Just for comparison: Using a Long
would enable you to store over 900 quadrillion records (900_000_000_000_000_000).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With