无法使用@PrimaryKey(autoGenerate = true) 进行更新
Unable to Update using @PrimaryKey(autoGenerate = true)
我正在使用 Room 并发现将主键设置为自动生成的问题,
@PrimaryKey(autoGenerate = true)
如果我执行了 INSERT 操作,然后执行了 UPDATE 操作,这些操作生成的密钥不同,因此我的数据不会得到更新。
@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;
}
}
这是一个 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);
}
这是我的 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;
}
}
我已将我的 LiveData 连接到我的存储库,但是,出于简单的原因,下面也执行相同的操作。
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);
}
});
我的问题是,使用@PrimaryKey(autoGenerate = true) 的模式是什么??通过对主键进行以下硬编码,我可以让一切都完美地工作,但我认为这不是必需的。
编辑
@PrimaryKey(autoGenerate = true)
private int uid = 1; <---- works with any hardcoded int value
My question is, what is the pattern for using @PrimaryKey(autoGenerate = true)??
- 它的简单整数从 0 开始,然后在添加行时递增 1。
Do I have to always retrieve the id, then with every update pass it in?
- 是的。
@Update - 来自文档
如果参数已经存在(通过主键检查),该方法的实现将更新数据库中的参数。如果它们不存在,此选项将不会更改数据库。
There has to be a better way. Any suggestions?
- 这取决于您的要求。
如果我没记错的话,我猜你一直试图在 table 中只保存一行。
@Query("UPDATE test_table where 1=1")
protected abstract int update(TestEntity te);
另一种方式。但是在这里你需要设置 uid
一些硬编码的整数。
由于您不存储多个,因此您不需要主键约束,任何上述逻辑都可以工作。
您创建一个 TestEntity
,然后告诉 Room 将其保存在数据库中。那时,Room 会为其分配一个自动生成的主键。如果你想更新那个特定的 TestEntity
,你必须传递一个 TestEntity
class 的实例,它具有与数据库正在使用的完全相同的 id(id 是在实体时自动生成的是第一次保存在数据库中,不是在你实例化的时候)。
因此,您必须知道要更新的实体的 ID。第一次保存时如何判断分配给它的是哪个id?您可以将 @Insert
方法 return 改为 Long,这将是 ID。
@Insert
Long insert(TestEntity testEntity);
所以,通过这个小改动,您现在可以知道数据库分配给最近保存的实体的 ID。然后,你可以将那个 Long 设置为 java 中的 Entity 实例,更改其他一些参数,然后调用 update,它将起作用,因为这次它们将具有相同的 id
我正在使用 Room 并发现将主键设置为自动生成的问题,
@PrimaryKey(autoGenerate = true)
如果我执行了 INSERT 操作,然后执行了 UPDATE 操作,这些操作生成的密钥不同,因此我的数据不会得到更新。
@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;
}
}
这是一个 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);
}
这是我的 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;
}
}
我已将我的 LiveData 连接到我的存储库,但是,出于简单的原因,下面也执行相同的操作。
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);
}
});
我的问题是,使用@PrimaryKey(autoGenerate = true) 的模式是什么??通过对主键进行以下硬编码,我可以让一切都完美地工作,但我认为这不是必需的。
编辑
@PrimaryKey(autoGenerate = true)
private int uid = 1; <---- works with any hardcoded int value
My question is, what is the pattern for using @PrimaryKey(autoGenerate = true)??
- 它的简单整数从 0 开始,然后在添加行时递增 1。
Do I have to always retrieve the id, then with every update pass it in?
- 是的。 @Update - 来自文档
如果参数已经存在(通过主键检查),该方法的实现将更新数据库中的参数。如果它们不存在,此选项将不会更改数据库。
There has to be a better way. Any suggestions?
- 这取决于您的要求。 如果我没记错的话,我猜你一直试图在 table 中只保存一行。
@Query("UPDATE test_table where 1=1")
protected abstract int update(TestEntity te);
另一种方式。但是在这里你需要设置 uid
一些硬编码的整数。
由于您不存储多个,因此您不需要主键约束,任何上述逻辑都可以工作。
您创建一个 TestEntity
,然后告诉 Room 将其保存在数据库中。那时,Room 会为其分配一个自动生成的主键。如果你想更新那个特定的 TestEntity
,你必须传递一个 TestEntity
class 的实例,它具有与数据库正在使用的完全相同的 id(id 是在实体时自动生成的是第一次保存在数据库中,不是在你实例化的时候)。
因此,您必须知道要更新的实体的 ID。第一次保存时如何判断分配给它的是哪个id?您可以将 @Insert
方法 return 改为 Long,这将是 ID。
@Insert
Long insert(TestEntity testEntity);
所以,通过这个小改动,您现在可以知道数据库分配给最近保存的实体的 ID。然后,你可以将那个 Long 设置为 java 中的 Entity 实例,更改其他一些参数,然后调用 update,它将起作用,因为这次它们将具有相同的 id