Android Java中如何解决“查询中的每个绑定变量必须具有匹配的方法参数”错误?

问题描述 投票:2回答:1

我试图在一个只有一个表和其中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();
java android database android-room
1个回答
2
投票

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循环)

测试

使用以下代码测试了代码:-

  • Task.java复制的论文,未更改
  • TaskDAO.java复制的论文,未更改。
  • 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();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.