我试图在一个只有一个表和其中Task对象的android应用中实现一个简单的RoomDB,并通过databaseBuilder的回调函数对其进行了预加载。当我尝试构建应用程序时,我得到查询中的每个绑定变量必须具有匹配的方法参数错误,但是如果我第二次点击运行,它将编译该应用程序,但是我无法在数据库中插入任何内容,并且我尝试通过其ID(0)查询预加载的任务,并返回null。
这是我的Task类,我想将其存储在数据库中:
@Entity(tableName = "tasks")
public class Task {
@PrimaryKey(autoGenerate = true)
private int taskId;
@ColumnInfo(name = "Description")
private String description;
public Task(String description) {
this.description = description;
}
public void setTaskId(int taskId) {
this.taskId = taskId;
}
public int getTaskId() {
return taskId;
}
public String getDescription() {
return description;
}
@NonNull
@Override
public String toString() {
return "Task object, id: "+taskId;
}
}
这是我的TaskDAO:
@Dao
public interface TaskDAO {
@Query("SELECT * FROM tasks")
List<Task> getAll();
@Query("SELECT * FROM tasks WHERE taskId = (:taskId)")
Task getTaskById(int taskId);
@Insert
void insertAll(Task...tasks);
}
这是数据库类:
@Database(entities = {Task.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract TaskDAO taskDAO();
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "tasks.db")
.addCallback(new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateInitialData(INSTANCE).execute();
}
}).build();
}
return INSTANCE;
}
private static class PopulateInitialData extends AsyncTask<Void, Void, Void> {
private final TaskDAO taskDAO;
public PopulateInitialData(AppDatabase database){
taskDAO = database.taskDAO();
}
@Override
protected Void doInBackground(Void... voids) {
Task task1 = new Task("Task data");
taskDAO.insertAll(new Task[] {task1});
return null;
}
}
}
这就是我调用数据库并尝试查询任务的方式:
AppDatabase roomDB = AppDatabase.getAppDatabase(getApplicationContext());
new Thread(new Runnable() {
@Override
public void run() {
Task task = roomDB.taskDAO().getTaskById(0)); //task is null
}
}).start();
insertAll方法需要一个Task对象(Task[]
)数组,而不是单个Task对象。
如果要插入单个Task对象,则可以在DAO中添加新的插入方法,例如
@Insert
void insertOneTask(Task task);
或者用当前的insertAll方法使用单个元素数组。
e.g。
taskDAO.insertAll(new Task[]{task1});
但是我无法将任何内容插入数据库,并且如果我尝试查询通过其ID(0)预加载的任务,它会返回null。
这是因为在正常情况下,永远不会有一个ID为0的任务。第一个ID为1。
如果使用以下代码,则>
List<Task> alltasks = roomDB.taskDAO().getAll(); for (Task t: alltasks) { Log.d("TASKINFO","Task =" + t.getDescription() + " ID = " + t.getTaskId()); }
Task task = roomDB.taskDAO().getTaskById(0)); //task is null
之后/之前或之前>它将显示任务ID为1。
e.g。 2019-09-29 20:00:20.463 D/TASKINFO: Task =Task data ID = 1
为了说明ROOM将使用:-]为任务创建表,
CREATE TABLE IF NOT EXISTS `tasks` (`taskId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `Description` TEXT)
taskid列,将是rowid列的别名,如果未提供值,或者提供的值为null。然后它将自动为rowid生成一个值,因此它是别名。该值将比上次记录的值或数据库中当前的最高值中的较高者大1。如果没有这样的值,则该值将为1
。如果您使用过
Task task = roomDB.taskDAO().getTaskById(1));
插入的任务将被返回。
通常,您永远不要对id的值进行假设,而应该以编程的方式(通常是从列表中获取),但是使用ROOM时,您通常会处理Objects(例如,如上所述的getAll()和以下for循环)
测试
使用以下代码测试了代码:-
AppDatabase.java
这就是我如何调用数据库并尝试查询任务:
将此代码放入MainActivity.java
MedroomDB是一个类变量,(AppDatabase roomDB)只是在onCreate方法中实例化了它。
也已纠正错误(附加括号)和
[从上面添加了getAll和循环代码。
按照:-
public class MainActivity extends AppCompatActivity {
AppDatabase roomDB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
roomDB = AppDatabase.getAppDatabase(getApplicationContext());
new Thread(new Runnable() {
@Override
public void run() {
Task task = roomDB.taskDAO().getTaskById(0); //task is null
List<Task> alltasks = roomDB.taskDAO().getAll();
for (Task t: alltasks) {
Log.d("TASKINFO","Task =" + t.getDescription() + " ID = " + t.getTaskId());
}
}
}).start();
}
}