当前位置: 首页 > 知识库问答 >
问题:

无法使用@PrimaryKey(autoGenerate=true)进行更新

阙项禹
2023-03-14

我正在使用Room,发现将主键设置为“自动生成”有问题,

@PrimaryKey(自动生成=真)

如果我执行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
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);
}

这是我的应用数据库

@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(自动生成=true)的模式是什么??我可以通过对主键进行以下硬编码来让一切完美地工作,但我认为这不是必需的。

编辑

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

共有2个答案

阳建弼
2023-03-14

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

  • 它的简单整数从0开始,然后在添加行时递增1

我是否必须始终检索id,然后在每次更新时将其传入?

  • 对@更新-来自文档

如果参数已经存在(通过主键检查),则该方法的实现将更新其在数据库中的参数。如果它们不存在,此选项将不会更改数据库。

一定有更好的办法。有什么建议吗?

  • 这取决于你的要求。若我并没有错的话,我猜你们一直试图在表中只保存一行

@查询(“更新测试表,其中1=1”)

受保护的抽象int更新(TestEntity te);

替代方式。但是在这里,您需要设置一些硬编码的整数。由于不存储多个,因此不需要主键约束,因此上述任何逻辑都可以工作。

牟飞沉
2023-03-14

您创建一个TestEntity,然后告诉Room将其保存在数据库中。此时,房间将为其分配一个自动生成的主键。然后,如果要更新特定的TestEntity,则必须传递一个TestEntity类的实例,该实例的id与数据库使用的id完全相同(该id是在实体首次保存在数据库中时自动生成的,而不是在实例化它时)。

因此,您必须知道要更新的实体的id。如何在第一次保存时告诉它分配了哪个id?您可以让您的@Inrett方法返回Long,这将是id。

@Insert
Long insert(TestEntity testEntity);

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

 类似资料:
  • 问题内容: 我正在尝试使我的网站页面无缝加载。如果单击下面某些链接上的页面,您将看到我在说什么。 http://www.ultranoir.com/ http://www.itsmassive.com/ 当您单击链接时,它将加载信息,并且/#!/添加到URL。如何添加此功能,以便页面以相同的方式加载?哪里有教程? 问题答案: 这称为事件。您可以在更改后的值而无需重新加载页面,然后可以使用AJAX加

  • 问题内容: 我有主GUI线程,其中有一个JprogressBar,并且正在实现ProprtyChangeListener。 当按下按钮时,扩展SwingWorker的其他类将开始执行并执行一系列可能很长的计算。我需要A类中的进度条以根据B类中的变量来呈现进度。 我的代码在下面(我所有失败的尝试都可能有点混乱…) 将不胜感激。 GUI类别: 计算类: 编辑 原始问题仍然存在。出于某种原因,进度条仍然

  • 我将primefaces 3.3与JSF 2.1结合使用。在下面的代码中,我有一个primeFaces dataTable,其中包含从数据库中提取的数据行,该数据库通过页面左侧的树组件正确激活。dataTable显示和行为正确。我有一个名为“更新”的删除功能,它刷新我的数据表,并在数据库更新后反映我的更改。我的问题是f:facet(id=“header”)。该方面包含一个commandLink,它

  • 问题内容: 我在Postgres 11.3数据库中有一个带有列的表。 尝试更新嵌套数组名称中的所有对象。 如果路径是对象,则应将路径从对象更新为具有以下值的字符串: 如果不存在该路径,则该对象应保持不变。 使用查询测试设置:小提琴链接 所需结果: 我已经修改了查询并链接到小提琴中。有人可以看看是否正确吗? 问题答案: 平原应该有所作为。 db <>在这里 拨弄 (Postgres 11!) 为了同

  • 我得到这个错误 食品项插入失败无法添加或更新子行:外键约束失败(.,约束外键()在更新级联上引用() 我试图以一种形式将食谱添加到我的数据库中。我希望输入的数据到3个不同的表。配料表、配方表和recipe_compridient表。recipe表中有一个自动增量id作为主键,而配料id作为recipe表中的外键。 我想要配料名称,数据到配料表和名称,课程,指令到配方表加上配料表中的配料ID 要转到

  • 问题内容: 我正在尝试使用SCAN http://redis.io/commands/scan来遍历redis中存在的所有键。但是spring提供的Redis模板没有任何scan()方法。有什么技巧可以使用以上内容吗? 谢谢 问题答案: 您可以使用on 来这样做。