sqlite 无法使用@PrimaryKey更新(AutoGenerate=True)

8mmmxcuj  于 2022-11-15  发布在  SQLite
关注(0)|答案(3)|浏览(389)

我正在使用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=真)的模式是什么?通过对主键执行以下硬编码,我可以让一切完美地工作,但我认为这不是必需的。
编辑

@PrimaryKey(autoGenerate = true)
    private int uid = 1; <---- works with any hardcoded int value
58wvjzkj

58wvjzkj1#

您创建一个TestEntity,然后告诉Room将其保存在数据库中。此时,Room为其分配一个自动生成的主键。如果要更新特定TestEntity,则必须使用与数据库使用的ID完全相同的ID传递TestEntity类的示例(该ID是在实体第一次保存到数据库中时自动生成的,而不是在示例化它时生成的)。
因此,您必须知道要更新的实体的ID。当它第一次保存时,如何判断分配给它的ID?您可以让@Insert方法返回一个LONG,它将是id。

@Insert
Long insert(TestEntity testEntity);

因此,只需稍作更改,您现在就可以知道数据库分配给最近保存的实体的ID。然后,您可以将该长度设置为Java中的Entity示例,更改其他一些参数,然后调用UPDATE,它就会起作用,因为这一次它们将具有相同的id

flvlnr44

flvlnr442#

我的问题是,使用@PrimaryKey(AutoGenerate=真)的模式是什么?

  • 它的简单整数从0开始,然后随着行的增加而递增1。

我是否必须总是检索id,然后在每次更新时传递它?

  • 是的。@更新-来自文档

如果数据库中的参数已经存在(由主键检查),则该方法的实现将更新其参数。如果它们不存在,则此选项不会更改数据库。
一定有更好的办法。有什么建议吗?

  • 这取决于您的要求。如果我没记错的话,我猜您一直都在尝试在表中只保存一行。

@Query(“UPDATE TEST_TABLE WHERE 1=1”)
受保护摘要INT UPDATE(TestEntity TE);
另一种方式。但在这里,您需要设置uid某个硬编码的整数。因为您不存储多个,所以不需要主键约束,上面的任何逻辑都将起作用。

uwopmtnx

uwopmtnx3#

@Entity
    class Note(
    @ColumnInfo(name = "title") var title: String,
    @ColumnInfo(name = "content") var content: String,
    @ColumnInfo(name = "timestamp") var timestamp: String,
    @ColumnInfo(name = "age") var age: Int
) {

  @PrimaryKey(autoGenerate = true)
  var id: Int? = null    

 }

将id设置为空很重要

相关问题