Issue
I am working with Room and have found an issue with setting primary key to autogenerate,
@PrimaryKey(autoGenerate = true)
If I do an INSERT operation and then follow that up with an UPDATE operation, the generated keys for these operations differ and therefore, my data does not get updated.
@Entity(tableName = "test_table")
public class TestEntity {
@PrimaryKey(autoGenerate = true)
private int uid;
@ColumnInfo(name = "expiration_date_access_token")
private String expirationDateAccessToken;
/**
* Getter for retrieving primary key
*
* @return Primary key
*/
public int getUid() {
return uid;
}
/**
* Setter for setting primary key
*
* @param uid Primary key
*/
public void setUid(int uid) {
this.uid = uid;
}
/**
* Getter for retrieving expiration date of access token
*
* @return Expiration date of access token
*/
public String getExpirationDateAccessToken() {
return expirationDateAccessToken;
}
/**
* Setter for setting expiration date of access token
*
* @param expirationDateAccessToken Expiration date of access token
*/
public void setExpirationDateAccessToken(String expirationDateAccessToken) {
this.expirationDateAccessToken = expirationDateAccessToken;
}
}
Here is an example DAO
@Dao
public interface TestDao {
@Query("SELECT * FROM test_table")
List<TestEntity> getAll();
@Query("DELETE FROM test_table")
void deleteAll();
@Insert
void insert(TestEntity testEntity);
@Delete
void delete(TestEntity testEntity);
@Update
void update(TestEntity testEntity);
}
Here is my AppDatabase
@Database(entities = {TestEntity.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
private static final String DATABASE_NAME = "room.test.db";
private static AppDatabase APP_DATABASE_INSTANCE;
public abstract TestDao testDao();
public static AppDatabase getAppdatabase(@NonNull Context context) {
if (FrameworkUtils.checkIfNull(APP_DATABASE_INSTANCE)) {
APP_DATABASE_INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, DATABASE_NAME).build();
}
return APP_DATABASE_INSTANCE;
}
/**
* Method is used to destroy database instance
*/
public static void destroy() {
APP_DATABASE_INSTANCE = null;
}
}
I have connected my LiveData to my repository, howevever, for simplistic reasons below also does the same operation.
Thread t = new Thread(new Runnable() {
@Override
public void run() {
// update database tables
TestEntity testEntity = new TestEntity();
// if I uncomment setting uid, which is the hardcoded primary key
// value, the update will happen. If I do not include this, and
// just try to update my data, a new primary key is generated and
// the old data does not get updated.
// testEntity.setUid(1);
testEntity.setExpirationDateAccessToken("12345");
AppDatabase.getAppdatabase(context).testDao().update(testEntity);
}
});
My question is, what is the pattern for using @PrimaryKey(autoGenerate = true)?? I can get everything to work perfectly by doing the following hardcoding of the primary key, but I did not think that was required.
EDIT
@PrimaryKey(autoGenerate = true)
private int uid = 1; <---- works with any hardcoded int value
Solution
You create a TestEntity
and then tell Room to save it in the database. At that point, Room assign to it a autogenerated primary key. If then you want to update that specific TestEntity
, you have to pass an instance of TestEntity
class with the exact same id that the database is using (the id is automatically generated when the entity is saved for the first time in the database, not when you instantiate it).
Therefore, you have to know the id of the entity you want to update. How to tell which id is assigned to it when it is first saved? You can make your @Insert
method return a Long instead, which will be the id.
@Insert
Long insert(TestEntity testEntity);
So, with that little change, you can now know which id the databse assigned to the recently saved Entity. Then, you can set that Long to the Entity instance in java, change some other parameter, and call update, and it will work because they will have the same id this time
Answered By - dglozano
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)