Android Room更新查询卡在自动生成的代码上

时间:2018-06-12 22:51:54

标签: android android-room

现在使用Android Room几个星期并获得基本查询后,我遇到了尝试更新自定义对象列表的问题。出于某种原因,当Room试图创建SQLLite字符串以插入我的新数据时,它会被占位符所困: 从调试窗口:

  

引起:android.database.sqlite.SQLiteException:near“?”:语法错误(代码1):,同时编译:UPDATE player_characters SET ability_scores =?,?,?,?,?,?哪里有playerCharacterID =?                     ################################################## ###############                     错误代码:1(SQLITE_ERROR)                     引起:SQL(查询)错误或缺少数据库。                       (接近“?”:语法错误(代码1):,编译时:UPDATE player_characters SET ability_scores =?,?,?,?,?,?WHERE playerCharacterID =?)                     ################################################## ###############                         在android.database.sqlite.SQLiteConnection.nativePrepareStatement(本机方法)                         在android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1005)                         在android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:570)                         在android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)                         在android.database.sqlite.SQLiteProgram。(SQLiteProgram.java:59)                         在android.database.sqlite.SQLiteStatement。(SQLiteStatement.java:31)                         在android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1375)                         在android.arch.persistence.db.framework.FrameworkSQLiteDatabase.compileStatement(FrameworkSQLiteDatabase.java:62)                         在android.arch.persistence.room.RoomDatabase.compileStatement(RoomDatabase.java:204)                         at com.pathfinderstattracker.pathfindercharactersheet.database.database_daos.PlayerCharacterDao_Impl.updatePlayerCharacterAbilityScores(PlayerCharacterDao_Impl.java:321)

包含查询的DAO:

@Dao
@TypeConverters({UUIDConverter.class,
                 AbilityScoreConcreteConverter.class})
public interface PlayerCharacterDao
{       
    @Query("UPDATE player_characters "+
           "SET ability_scores = :playerCharacterAbilityScores "+
           "WHERE playerCharacterID = :characterIDToUpdate")
    void updatePlayerCharacterAbilityScores(UUID characterIDToUpdate, List<AbilityScore> playerCharacterAbilityScores);
}

调用它的repository命令:

private static class updatePlayerCharacterAbilityScoresAsyncTask extends AsyncTask<Object, Void, Void>
{
    private PlayerCharacterDao asyncPlayerCharacterDao;
    updatePlayerCharacterAbilityScoresAsyncTask(PlayerCharacterDao dao) {asyncPlayerCharacterDao = dao;}
    @Override
    protected Void doInBackground(final Object... params)
    {
        UUID playerCharacterID = (UUID)params[0];
        List<AbilityScore> updatedAbilityScores = (ArrayList<AbilityScore>)params[1];
        asyncPlayerCharacterDao.updatePlayerCharacterAbilityScores(playerCharacterID, updatedAbilityScores);
        return null;
    }
}

我可以确认数据是否正确地进入房间查询,并且我已经尝试将具体和接口对象传递到查询中,并且具有针对各个AbilityScore对象和AbilityScore对象列表的转换器。任何帮助将不胜感激!

编辑:有些人要求更新的实体:

@Entity(tableName = "player_characters")
@TypeConverters({AlignmentEnumConverter.class,
                 HitPointsConverter.class,
                 DamageReductionConverter.class,
                 StringListConverter.class,
                 UUIDConverter.class,
                 StringListConverter.class,
                 AbilityScoreListConverter.class,
                 CombatManeuverConverter.class})
public class PlayerCharacterEntity
{
    @PrimaryKey
    @NonNull
    private UUID playerCharacterID;
    @ColumnInfo(name="character_name")
    private String playerCharacterName;
    @ColumnInfo(name="character_level")
    private int characterLevel;
    @ColumnInfo(name="concentration_check")
    private int concentrationCheck;
    @ColumnInfo(name="character_alignment")
    private AlignmentEnum characterAlignment;
    @ColumnInfo(name="total_base_attack_bonus")
    private int totalBaseAttackBonus;
    @ColumnInfo(name="total_hit_points")
    private IHitPoints totalHitPoints;
    @ColumnInfo(name="total_ac")
    private int totalAC;
    @ColumnInfo(name="damage_reduction")
    private IDamageReduction damageReduction;
    @ColumnInfo(name="languages_known")
    private List<String> languagesKnown;
    @ColumnInfo(name="ability_scores")
    private List<IAbilityScore> abilityScores;
    @ColumnInfo(name="combat_Maneuver_stats")
    private ICombatManeuver combatManeuverStats;
    @ColumnInfo(name="spell_resistance")
    private int spellResistance;
    @ColumnInfo(name="initiative")
    private int initiative;
    @ColumnInfo(name="fortitude_save")
    private int fortitudeSave;
    @ColumnInfo(name="reflex_save")
    private int reflexSave;
    @ColumnInfo(name="will_save")
    private int willSave;

    ~Getters/Setters and Constructors removed for brevity~
}

编辑:为了更好的衡量,我认为我会为AbilityScore包含@TypeConverter(我已经将其恢复为使用接口而不是具体的早期形式,因为它在代码中的其他位置起作用并且差异似乎没有改变任何东西):

public class AbilityScoreConverter
{
    @TypeConverter
    public IAbilityScore fromString(String value)
    {
        IAbilityScore formattedAbilityScore = new AbilityScore();
        String[] tokens = value.split(" ");
        formattedAbilityScore.setAmount(Integer.parseInt(tokens[0]));
        switch(tokens[1])
        {
            case "STR":
                formattedAbilityScore.setStat(AbilityScoreEnum.STR);
            case "DEX":
                formattedAbilityScore.setStat(AbilityScoreEnum.DEX);
            case "CON":
                formattedAbilityScore.setStat(AbilityScoreEnum.CON);
            case "INT":
                formattedAbilityScore.setStat(AbilityScoreEnum.INT);
            case "WIS":
                formattedAbilityScore.setStat(AbilityScoreEnum.WIS);
            case "CHA":
                formattedAbilityScore.setStat(AbilityScoreEnum.CHA);
            default:
                //This may cause issues down the line if a non existent enum gets in the db somehow, but we don't have any error handling yet
                //Todo: Add error handling
                formattedAbilityScore.setStat(AbilityScoreEnum.STR);
        }

        return formattedAbilityScore;
    }

    @TypeConverter
    public String toString(IAbilityScore value)
    {
        return value.toString();
    }
}

编辑:我已经清理了logcat文本,只关注Room / SQLLite问题。

2 个答案:

答案 0 :(得分:0)

不幸的是,经过一番搜索,我被迫放弃使用@Query命令更新数据库,而不得不依靠Rooms default @Update表示法退回。虽然这样做确实有效,并且可以正确更新数据库中的数据,但不允许我仅更新某些字段。

答案 1 :(得分:0)

在我的UPDATE查询中使用ArrayList而不是List。

我遵循了solution

Impl版本的区别:

MutableList:

select t2.insco from table1 t1
join table2 t2 on t1.ins1=t2.insco
union
select t2.insco from table1 t1
join table2 t2 on t1.ins2=t2.insco
union
select t2.insco from table1 t1
join table2 t2 on t1.ins3=t2.insco

ArrayList:

@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);

如您所见,ArrayList使用转换器,而MutableList不使用转换器。

相关问题