为什么Room数据库ID在日志/Toast消息中都显示为0



我正在尝试使用Android的Room将最后插入的对象的id获取到数据库中。我可以使用SQL查询获取最后一个对象,并可以调用其他方法来获取用户在保存对象时设置的该对象的各种属性。但是getId((总是返回0。当我在安卓工作室的应用程序检查器中检查表内容时,我可以清楚地看到Room正在为每一行生成一个唯一的主键,但我就是看不懂。有人能告诉我可能是什么问题吗?

这是道的查询:

@Query("SELECT * FROM gamebooks_table WHERE gamebookId=gamebookId ORDER BY gamebookId DESC LIMIT 1")
LiveData<Gamebook> getSingleGamebookByID();

这是带注释的实体类:

@Entity(tableName = "gamebooks_table")
public class Gamebook {   
@PrimaryKey(autoGenerate = true)
private long gamebookId;
private String gamebookName;
private String gamebookComment;
private String gamebookPublisher;
private float gamebookStarRating;
public Gamebook(String gamebookName, String gamebookComment, String gamebookPublisher, float gamebookStarRating) {
this.gamebookName = gamebookName;
this.gamebookComment = gamebookComment;
this.gamebookPublisher = gamebookPublisher;
this.gamebookStarRating = gamebookStarRating;
}
public long getGamebookId() {
return gamebookId;
}
public String getGamebookName() {
return gamebookName;
}
public String getGamebookComment() {
return gamebookComment;
}
public String getGamebookPublisher() {
return gamebookPublisher;
}
public float getGamebookStarRating(){
return gamebookStarRating;
}
public void setGamebookId(long gamebookId) {
this.gamebookId = gamebookId;
}
}

SOLVED最后通过在我的DAO方法中添加一个Observer对其进行排序,该方法返回一个游戏本。在Observer的onChanged((方法中,我可以循环浏览LiveData List中的所有Gamebook(尽管只有一个,因为我在SQL查询中将其限制为一个(,并调用getId((来获取它们各自的ID。

mainViewModel.getSingleGamebook().observe(this, new Observer<List<Gamebook>>() {
@Override
public void onChanged(List<Gamebook> gamebooks) {
int i=0;
for(Gamebook gamebook : gamebooks){
gamebookId= gamebook.getGamebookId();
Log.d(TAG, "Gamebook Name: "+gamebook.getGamebookName()+ " Database ID: " +gamebookId);
i++;
}
}
});

我认为您的问题是由于唯一可用的构造函数没有设置id,因此LiveData长时间使用默认值0。

我建议使用一个默认的构造函数,从而使用所有的setter/getter,并(可选(为其中一个构造函数使用@Ignore注释。。

  • 如果没有@Ignore,则会收到警告Gamebook.java:8: warning: There are multiple good constructors and Room will pick the no-arg constructor. You can use the @Ignore annotation to eliminate unwanted constructors. public class Gamebook {

例如:-

@Entity(tableName = "gamebooks_table")
public class Gamebook {
@PrimaryKey(autoGenerate = true)
private long gamebookId;
private String gamebookName;
private String gamebookComment;
private String gamebookPublisher;
private float gamebookStarRating;

public Gamebook(){} /*<<<<< ADDED */
@Ignore /*<<<<< ADDED - is not required - could be on the default constructor but not both*/
public Gamebook(String gamebookName, String gamebookComment, String gamebookPublisher, float gamebookStarRating) {
this.gamebookName = gamebookName;
this.gamebookComment = gamebookComment;
this.gamebookPublisher = gamebookPublisher;
this.gamebookStarRating = gamebookStarRating;
}
public long getGamebookId() {
return gamebookId;
}
public String getGamebookName() {
return gamebookName;
}
public String getGamebookComment() {
return gamebookComment;
}
public String getGamebookPublisher() {
return gamebookPublisher;
}
public float getGamebookStarRating(){
return gamebookStarRating;
}
public void setGamebookId(long gamebookId) {
this.gamebookId = gamebookId;
}
/* ADDED setters */
public void setGamebookName(String gamebookName) {
this.gamebookName = gamebookName;
}
public void setGamebookComment(String gamebookComment) {
this.gamebookComment = gamebookComment;
}
public void setGamebookPublisher(String gamebookPublisher) {
this.gamebookPublisher = gamebookPublisher;
}
public void setGamebookStarRating(float gamebookStarRating) {
this.gamebookStarRating = gamebookStarRating;
}
}

您可能还希望能够将相应的id传递给getSingleGamebookByID,因此您可能希望将其更改为:-

@Query("SELECT * FROM gamebooks_table WHERE gamebookId=:gamebookId /*<<<<< ADDED to use id passed */ ORDER BY gamebookId DESC LIMIT 1")
LiveData<Gamebook> getSingleGamebookByID(long gamebookId /*<<<<< ADDED to use id passed */);
  • 您可能想要删除注释

请注意,LiveData方面尚未经过测试,只是推测


示例

这个例子表明,房间对你的原始代码很好,但问题在LiveData/Viewmodel方面:-

public class MainActivity extends AppCompatActivity {
TheDatabase db;
GamebookDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Note The Database has .allowMainThreadQueries */
db = TheDatabase.getInstance(this);
dao = db.getGamebookDao();
long gb1id = dao.insert(new Gamebook("Gamebook1","blah","Gamebook1 Publisher", 10.1F));
long gb2id = dao.insert(new Gamebook("Gamebook2","blah","Gamebook2 Publisher", 6.1F));
long gb3id = dao.insert(new Gamebook("Gamebook3","blah","Gamebook3 Publisher", 10.1F));
logGameBook(dao.getSingleGamebookByID());
logGameBook(dao.getSingleGamebookByID());
logGameBook(dao.getSingleGamebookByID());
/* Alternative that allows the ID to be specified */
logGameBook(dao.getSingleGamebookByIDAlternative(gb1id));
logGameBook(dao.getSingleGamebookByIDAlternative(gb2id));
logGameBook(dao.getSingleGamebookByIDAlternative(gb3id));
}
void logGameBook(Gamebook gb) {
Log.d("GAMEBOOKINFO","Gamebook is " + gb.getGamebookName() + " id is " + gb.getGamebookId());
}
}
  • 上面使用了您的原始代码,TheDatabase是一个基本的@Database注释类,但带有.allowMainThreadQueries,因此它在主线程上运行

运行后的日志包括:-

2022-03-12 08:16:12.556 D/GAMEBOOKINFO: Gamebook is Gamebook3 id is 3
2022-03-12 08:16:12.558 I/chatty: uid=10132(a.a.so71429144javaroomidreturnedaszero) identical 1 line
2022-03-12 08:16:12.561 D/GAMEBOOKINFO: Gamebook is Gamebook3 id is 3
2022-03-12 08:16:12.568 D/GAMEBOOKINFO: Gamebook is Gamebook1 id is 1
2022-03-12 08:16:12.572 D/GAMEBOOKINFO: Gamebook is Gamebook2 id is 2
2022-03-12 08:16:12.574 D/GAMEBOOKINFO: Gamebook is Gamebook3 id is 3
  • 注意第一个是如何返回相同的对象,从而返回id的

最新更新