仅当原始值为 0 时,带有数学函数的房间查询才有效

Room query with math functions only works when original value is 0

提问人:Alex T 提问时间:9/23/2022 最后编辑:Alex T 更新时间:10/1/2022 访问量:188

问:

在 Android Studio 上构建一个充满数据的数据库,使用 Java 和 Room(而不是 kotlin)。有些列是文本,有些是带有小数的数字。但是,除第一列(id、主键)外,所有列都标识为文本。

用户写入一个值(sphecornea)并提交...应用应返回与该值匹配的所有行。

算法 .java 包含此函数

 public void cnvalgorithm (View view) {
        EditText sphecornea = findViewById(R.id.sphecornea);
        String sphecorneastr = sphecornea.getText().toString();
                AppExecutors.getInstance().diskIO().execute(() -> {
                  final List<Person> persons = mDb.personDao().loadPersonByAbe(sphecorneastr);
            runOnUiThread(() -> mAdapter.setTasks(persons));
        });
    }

人道

@Query("SELECT id,firm,model,aberration_correction FROM PERSON" + " WHERE aberration_correction = :sphecorneastr")
public List<Person> loadPersonByAbe(String sphecorneastr);

按原样,只有当输入的值为 0 时,我才会得到正确的结果。对于任何其他数字,结果都是空的。 我认为系统无法将“-0.20”识别为数字,因此我尝试通过更改Dao和Algorithm .java部分将其操作为Double。然后,我根本没有得到任何结果。

更新:

我刚刚意识到该应用程序不会将数据(0 除外)视为数字。我尝试了这段代码(我知道非常不优雅)。它添加了 0+1,但在处理任何其他数字时会崩溃......

Double aberration_correctiondou = Double.parseDouble(mPersonList.get(i).getAberration_correction());
Double aberration_correctiondou2 = aberration_correctiondou + 1;
        myViewHolder.aberration_correction.setText(String.valueOf(aberration_correctiondou2));

更新2:

实体

为了您的心理健康,我删除了实体文件的许多行(db 的更多列)。


@Entity(tableName = "person")
public class Person {
    @PrimaryKey(autoGenerate = true)
    int id;
    public String firm;
    public String model;
    public String aberration_correction;
    

    @Ignore
    public Person(String    firm    ,     String    model   ,
                  String    aberration_correction   ,
                   {
        this.   firm    =   firm    ;
        this.   model   =   model   ;
        this.   aberration_correction   =   aberration_correction   ;
        
    }

    public Person(int id, String    firm    ,
                  String    model   ,
                  String    aberration_correction   ,
                  
                  ) {
        this.id = id;
        this.   firm    =   firm    ;
        this.   model   =   model   ;
        this.   aberration_correction   =   aberration_correction   ;
        
    }

    public static final String[] PERSONS = {

    };

    public Person() {

    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public String getFirm   () {return  firm    ;} public void setFirm  (String     firm    ){this. firm    =   firm    ;}
    public String getModel  () {return  model   ;} public void setModel (String     model   ){this. model   =   model   ;}
    public String getAberration_correction  () {return  aberration_correction   ;} public void setAberration_correction (String     aberration_correction   ){this. aberration_correction   =   aberration_correction   ;}
    
}

数据库快照:似乎我没有足够的点来上传图像,提供了一个链接

解决方案:正如@MikeT所建议的那样,数据库中的小数点应以“.”而不是“,”分隔。

数据库 数学 数字 android-room

评论


答:

0赞 MikeT 9/23/2022 #1

尝试

@Query("SELECT id,firm,model,aberration_correction FROM PERSON" + " WHERE round(CAST(aberration_correction AS REAL),2) = round(CAST(:sphecorneastr AS REAL),2)"

或:-

@Query("SELECT id,firm,model,aberration_correction FROM PERSON" + " WHERE round(aberration_correction,2) = round(:sphecorneastr,2)")

这应该转换字符串文字(因为 Room 会将值括在单引号中,因此“-0.2”)。

查看 https://www.sqlite.org/lang_expr.html#castexpr 查看 https://www.sqlite.org/lang_corefunc.html#round

双精度存储非常高,例如,-0.20 不会这样存储,而是存储为 -0.200000000000000093(或 -0.1950000000000000092)。

演示

也许考虑这个例子/演示:-

首先是 Person 类:-

@Entity
class Person {
    @PrimaryKey
    Long id=null;
    String firm;
    String model;
    String aberration_correction;
    double aberration_correction_double;

    Person(){}
    @Ignore
    Person(Long id,String firm, String model, double aberration_correction) {
        this.id  = id;
        this.firm = firm;
        this.model = model;
        this.aberration_correction = String.valueOf(aberration_correction);
        this.aberration_correction_double = aberration_correction;
    }
    @Ignore
    Person(String firm, String model, double aberration_correction) {
        this.id = null;
        this.firm = firm;
        this.model = model;
        this.aberration_correction = String.valueOf(aberration_correction);
        this.aberration_correction_double = aberration_correction;
    }
}
  • 请注意,更正同时具有 double 和 String 表示形式(均基于 double)

带注释的抽象类(可以是接口)PersonDao:-@Dao

@Dao
abstract class PersonDao {
   @Insert(onConflict = OnConflictStrategy.IGNORE)
   abstract long insert(Person person);
   @Query("SELECT id,firm,model,aberration_correction, aberration_correction_double FROM PERSON" + " WHERE round(CAST(aberration_correction AS REAL),2) = round(CAST(:sphecorneastr AS REAL),2)")
   abstract List<Person> getPeopleByCorrection(String sphecorneastr);
   @Query("SELECT id,firm,model,aberration_correction, aberration_correction_double FROM PERSON" + " WHERE round(aberration_correction,2) = round(:sphecorneastr,2)")
   abstract List<Person> getPeopleByCorrectionV2(String sphecorneastr);
}

在活动中使用带有(方便和简洁)和以下代码的基本带注释的类:-@Database.allowMainThreadQueries

public class MainActivity extends AppCompatActivity {

    TheDatabase db;
    PersonDao dao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        db = TheDatabase.getInstance(this);
        dao = db.getPersonDao();

        Double correction = 1.0;
        for (int i=0;i<1000;i++) {
            dao.insert(new Person("Firm" + i,"Model" + i,correction));
            correction = correction - 0.005;
        }

        correction = -0.20;
        for (Person p: dao.getPeopleByCorrection(correction.toString())) {
            Log.d("DBINFO","Firm is " + p.firm + " Model is " + p.model + " C1 is " + p.aberration_correction + " C2 is " + p.aberration_correction_double);
        }
        for (Person p: dao.getPeopleByCorrectionV2(correction.toString())) {
            Log.d("DBINFO","Firm is " + p.firm + " Model is " + p.model + " C1 is " + p.aberration_correction + " C2 is " + p.aberration_correction_double);
        }
    }
}

将插入 1000 行,校正值从 1.0 到接近 - 4.0,递减 0.005(从而覆盖 -0.20 值)。

然后使用这两个查询,显示不需要 CAST,但需要轮次。

当运行时(仅设计为运行一次),则日志包括:-

2022-09-25 07:27:42.838 D/DBINFO: Firm is Firm239 Model is Model239 C1 is -0.19500000000000092 C2 is -0.19500000000000092
2022-09-25 07:27:42.839 D/DBINFO: Firm is Firm240 Model is Model240 C1 is -0.20000000000000093 C2 is -0.20000000000000093


2022-09-25 07:27:42.841 D/DBINFO: Firm is Firm239 Model is Model239 C1 is -0.19500000000000092 C2 is -0.19500000000000092
2022-09-25 07:27:42.841 D/DBINFO: Firm is Firm240 Model is Model240 C1 is -0.20000000000000093 C2 is -0.20000000000000093

可以看出,在任何一种情况下,-0.20 都不是存储值,但通过四舍五入到 2 dp,即可获得接近的值。您可能需要调整舍入以适应。

查看存储的实际数据,通过应用程序检查,然后

最初的行是:-

![enter image description here

最后一行是:-

enter image description here

-0.20 标记周围的行是:-

enter image description here

  • 突出显示提取的行

其他(在提供实体和实际数据后)

问题 1.

该实体指示您应该将 aberration_correction_double 列用于 WHERE 子句,而不是 aberration_correction 列(后者似乎只存储 0 或 1,可能表示布尔值)

问题 2.

屏幕截图在双精度中显示 s,您会期望一个句点。例如 而不是预期的.SQLite 将 ,如果要求 REAL(double),则返回 0(因此 0 定位所有)。,-0,20-0.20

不知道是如何进入数据的,但这就是问题所在。解决方法是使用:-,

@Query("SELECT id,firm,model,aberration_correction_double FROM PERSON" + " WHERE round(CAST(replace(aberration_correction_double,',','') AS REAL),2) = round(CAST(replace(:sphecorneastr,',','') AS REAL),2);"
  • 可能过头了,因为您可能只需要第一次更换。

你不妨考虑更新基础数据,例如一次性更新:

@Query("UPDATE PERSON SET aberration_correction_double = CAST(replace(aberration_correction_double,',','') AS REAL), aberration_correction = CAST(replace(aberration_correction_double,',','') AS TEXT) WHERE instr(aberration_correction_double,',');"
  • 这假定两列应包含相同的值。

评论

0赞 Alex T 9/24/2022
对不起,但它不起作用。仍然得到相同的结果,只有当输入值 0 时,该函数才起作用。任何其他数字,例如 0.20、-0.20、-0.18...不匹配。数据库加载了它们。每当我进行查询“显示所有数据”时,它们都会加载。但匹配的查询不起作用......
0赞 MikeT 9/25/2022
@AlexT更改为四舍五入为 2 dp。如果这不起作用,请编辑您的问题并包括 1) person 表的带注释类和 2) 示例实际数据(您可以使用 App Inspection 查看数据库,也可以在 App Inspection 中对实际数据运行查询)。@Entity
0赞 MikeT 9/25/2022
@AlexT答案已更新,包括演示。
0赞 Alex T 9/29/2022
对不起,我似乎无法让它工作。我已经尝试了您的解决方案...现在,当使用 0 时,所有结果都会显示(甚至是 -0,2 等),但没有一个结果与任何其他数字一起显示。我将用@entity和实际数据更新开篇文章。
0赞 MikeT 9/29/2022
@AlexT更新了答案。两个问题,2 列和使用逗号而不是句点。