在房间数据库中更新 List<Boolean> 时 TypeConverter 不工作
TypeConverter not working when updating List<Boolean> in Room Database
出于某种原因,我的查询在 DAO_Impl 构建中显示语法错误。我尝试重建,但在执行以下查询时仍然出错:
查询:
@Query("UPDATE TasksTable SET daysOfWeek = :days WHERE taskID = :tkID")
fun updateDays(tkID: Int, days: MutableList<Boolean>)
实体任务:
data class EntityTask(
var taskID: Int = 0,
var personID : Int = 0,
var name : String = "",
var frequency: Int = 1,
var interval: Int = 0,
var haveSchedule: Boolean = false,
var schedule: Int = 0,
var scheduleString: String = "",
var description: String = "",
var showProgressLayout: Boolean = true,
var daysOfWeek: MutableList<Boolean> = mutableListOf(),
var daysOfMonth: MutableList<Boolean> = mutableListOf(),
var currentScores: ScoresCurrent = ScoresCurrent(),
@Ignore
var scores : MutableList<EntityScore> = mutableListOf()
)
DaoTasks_Impl:
@Override
public void updateDays(int tkID, List<Boolean> days) {
StringBuilder _stringBuilder = StringUtil.newStringBuilder();
_stringBuilder.append("UPDATE TasksTable SET daysOfWeek = ");
final int _inputSize = days.size();
StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
_stringBuilder.append(" WHERE taskID = ");
_stringBuilder.append("?");
final String _sql = _stringBuilder.toString();
SupportSQLiteStatement _stmt = __db.compileStatement(_sql); //This is line 330
错误信息:
03-01 07:05:37.504 26855-27552/com.samuelriesterer.taskprogress E/SQLiteLog: (1) near "?": syntax error
03-01 07:05:37.514 26855-27552/com.samuelriesterer.taskprogress E/AndroidRuntime: FATAL EXCEPTION: Thread-23439
Process: com.samuelriesterer.taskprogress, PID: 26855
android.database.sqlite.SQLiteException: near "?": syntax error (code 1): , while compiling: UPDATE TasksTable SET daysOfWeek = ?,?,?,?,?,?,? WHERE taskID = ?
#################################################################
Error Code : 1 (SQLITE_ERROR)
Caused By : SQL(query) error or missing database.
(near "?": syntax error (code 1): , while compiling: UPDATE TasksTable SET daysOfWeek = ?,?,?,?,?,?,? WHERE taskID = ?)
#################################################################
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1058)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:623)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:59)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1132)
at android.arch.persistence.db.framework.FrameworkSQLiteDatabase.compileStatement(FrameworkSQLiteDatabase.java:64)
at android.arch.persistence.room.RoomDatabase.compileStatement(RoomDatabase.java:244)
at com.samuelriesterer.taskprogress.data.daos.DAOTasks_Impl.updateDays(DAOTasks_Impl.java:310)
at com.samuelriesterer.taskprogress.data.Data$Companion$editTask$thread.run(Data.kt:569)
at java.lang.Thread.run(Thread.java:818)
我有一个类型转换器,所以我不知道为什么它不允许我更新列表。我知道我的类型转换器可以工作,因为它在将列表添加到数据库时可以工作。 (它已添加到我的数据库中)。它只是在更新查询中使用时不起作用。
我的转换器:
@TypeConverter fun stringToListBoolean(value: String): MutableList<Boolean>
{
val list = mutableListOf<Boolean>()
value.forEach { c ->
if(c == 'F') list.add(false)
else list.add(true)
}
return list
}
@TypeConverter fun listBooleanToString(list: MutableList<Boolean>): String
{
var value = ""
for(i in list)
{
if(i) value += "T"
else value += "F"
}
return value
}
对这个修复不太满意,但我最终通过创建一个单独的 class 来达到我的目的,它保存列表 daysOfWeek 和 daysOfMonth:
的值
区间:
class Interval(_daysOfWeek: MutableList<Boolean> = mutableListOf(false, false, false, false, false, false, false),
_daysOfMonth: MutableList<Boolean> = mutableListOf(false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false)
)
{
val daysOfWeek = _daysOfWeek
val daysOfMonth = _daysOfMonth
}
然后为此添加了一个自定义转换器。现在我可以查询更新了:
@Query("UPDATE TasksTable SET name = :name, frequency = :frequency, interval = :interval, haveSchedule = :haveSchedule, schedule = :schedule, scheduleString = :scheduleString, description = :description, showProgressLayout = :showProgressLayout, intervals = :intervals WHERE taskID = :taskID")
fun updateTask(taskID: Int, name: String, frequency: Int, interval: Int, haveSchedule: Boolean, schedule: Int, scheduleString: String, description: String, showProgressLayout: Boolean, intervals: Interval)
因此,根据 Jeel Vankhede 的建议,我将 MutableList 更改为 ArrayList,并且 UPDATE 查询有效。 Impl 构建的差异:
可变列表:
@Override
public void test(int tkID, List<Boolean> test) {
StringBuilder _stringBuilder = StringUtil.newStringBuilder();
_stringBuilder.append("UPDATE TasksTable SET test = ");
final int _inputSize = test.size();
StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
_stringBuilder.append(" WHERE taskID = ");
_stringBuilder.append("?");
final String _sql = _stringBuilder.toString();
SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
数组列表:
@Override
public void test(int tkID, ArrayList<Boolean> test) {
final SupportSQLiteStatement _stmt = __preparedStmtOfTest.acquire();
__db.beginTransaction();
try {
int _argIndex = 1;
final String _tmp;
_tmp = Converters.listBooleanToString(test);
if (_tmp == null) {
_stmt.bindNull(_argIndex);
} else {
_stmt.bindString(_argIndex, _tmp);
}
_argIndex = 2;
_stmt.bindLong(_argIndex, tkID);
_stmt.executeUpdateDelete();
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
__preparedStmtOfTest.release(_stmt);
}
}
如您所见,ArrayList 使用了转换器,而 MutableList 没有。不知道这是为什么??
出于某种原因,我的查询在 DAO_Impl 构建中显示语法错误。我尝试重建,但在执行以下查询时仍然出错:
查询:
@Query("UPDATE TasksTable SET daysOfWeek = :days WHERE taskID = :tkID")
fun updateDays(tkID: Int, days: MutableList<Boolean>)
实体任务:
data class EntityTask(
var taskID: Int = 0,
var personID : Int = 0,
var name : String = "",
var frequency: Int = 1,
var interval: Int = 0,
var haveSchedule: Boolean = false,
var schedule: Int = 0,
var scheduleString: String = "",
var description: String = "",
var showProgressLayout: Boolean = true,
var daysOfWeek: MutableList<Boolean> = mutableListOf(),
var daysOfMonth: MutableList<Boolean> = mutableListOf(),
var currentScores: ScoresCurrent = ScoresCurrent(),
@Ignore
var scores : MutableList<EntityScore> = mutableListOf()
)
DaoTasks_Impl:
@Override
public void updateDays(int tkID, List<Boolean> days) {
StringBuilder _stringBuilder = StringUtil.newStringBuilder();
_stringBuilder.append("UPDATE TasksTable SET daysOfWeek = ");
final int _inputSize = days.size();
StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
_stringBuilder.append(" WHERE taskID = ");
_stringBuilder.append("?");
final String _sql = _stringBuilder.toString();
SupportSQLiteStatement _stmt = __db.compileStatement(_sql); //This is line 330
错误信息:
03-01 07:05:37.504 26855-27552/com.samuelriesterer.taskprogress E/SQLiteLog: (1) near "?": syntax error
03-01 07:05:37.514 26855-27552/com.samuelriesterer.taskprogress E/AndroidRuntime: FATAL EXCEPTION: Thread-23439
Process: com.samuelriesterer.taskprogress, PID: 26855
android.database.sqlite.SQLiteException: near "?": syntax error (code 1): , while compiling: UPDATE TasksTable SET daysOfWeek = ?,?,?,?,?,?,? WHERE taskID = ?
#################################################################
Error Code : 1 (SQLITE_ERROR)
Caused By : SQL(query) error or missing database.
(near "?": syntax error (code 1): , while compiling: UPDATE TasksTable SET daysOfWeek = ?,?,?,?,?,?,? WHERE taskID = ?)
#################################################################
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1058)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:623)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:59)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1132)
at android.arch.persistence.db.framework.FrameworkSQLiteDatabase.compileStatement(FrameworkSQLiteDatabase.java:64)
at android.arch.persistence.room.RoomDatabase.compileStatement(RoomDatabase.java:244)
at com.samuelriesterer.taskprogress.data.daos.DAOTasks_Impl.updateDays(DAOTasks_Impl.java:310)
at com.samuelriesterer.taskprogress.data.Data$Companion$editTask$thread.run(Data.kt:569)
at java.lang.Thread.run(Thread.java:818)
我有一个类型转换器,所以我不知道为什么它不允许我更新列表。我知道我的类型转换器可以工作,因为它在将列表添加到数据库时可以工作。 (它已添加到我的数据库中)。它只是在更新查询中使用时不起作用。
我的转换器:
@TypeConverter fun stringToListBoolean(value: String): MutableList<Boolean>
{
val list = mutableListOf<Boolean>()
value.forEach { c ->
if(c == 'F') list.add(false)
else list.add(true)
}
return list
}
@TypeConverter fun listBooleanToString(list: MutableList<Boolean>): String
{
var value = ""
for(i in list)
{
if(i) value += "T"
else value += "F"
}
return value
}
对这个修复不太满意,但我最终通过创建一个单独的 class 来达到我的目的,它保存列表 daysOfWeek 和 daysOfMonth:
的值区间:
class Interval(_daysOfWeek: MutableList<Boolean> = mutableListOf(false, false, false, false, false, false, false),
_daysOfMonth: MutableList<Boolean> = mutableListOf(false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false)
)
{
val daysOfWeek = _daysOfWeek
val daysOfMonth = _daysOfMonth
}
然后为此添加了一个自定义转换器。现在我可以查询更新了:
@Query("UPDATE TasksTable SET name = :name, frequency = :frequency, interval = :interval, haveSchedule = :haveSchedule, schedule = :schedule, scheduleString = :scheduleString, description = :description, showProgressLayout = :showProgressLayout, intervals = :intervals WHERE taskID = :taskID")
fun updateTask(taskID: Int, name: String, frequency: Int, interval: Int, haveSchedule: Boolean, schedule: Int, scheduleString: String, description: String, showProgressLayout: Boolean, intervals: Interval)
因此,根据 Jeel Vankhede 的建议,我将 MutableList 更改为 ArrayList,并且 UPDATE 查询有效。 Impl 构建的差异:
可变列表:
@Override
public void test(int tkID, List<Boolean> test) {
StringBuilder _stringBuilder = StringUtil.newStringBuilder();
_stringBuilder.append("UPDATE TasksTable SET test = ");
final int _inputSize = test.size();
StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
_stringBuilder.append(" WHERE taskID = ");
_stringBuilder.append("?");
final String _sql = _stringBuilder.toString();
SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
数组列表:
@Override
public void test(int tkID, ArrayList<Boolean> test) {
final SupportSQLiteStatement _stmt = __preparedStmtOfTest.acquire();
__db.beginTransaction();
try {
int _argIndex = 1;
final String _tmp;
_tmp = Converters.listBooleanToString(test);
if (_tmp == null) {
_stmt.bindNull(_argIndex);
} else {
_stmt.bindString(_argIndex, _tmp);
}
_argIndex = 2;
_stmt.bindLong(_argIndex, tkID);
_stmt.executeUpdateDelete();
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
__preparedStmtOfTest.release(_stmt);
}
}
如您所见,ArrayList 使用了转换器,而 MutableList 没有。不知道这是为什么??