提问人:Alex T 提问时间:9/23/2022 最后编辑:Alex T 更新时间:10/1/2022 访问量:188
仅当原始值为 0 时,带有数学函数的房间查询才有效
Room query with math functions only works when original value is 0
问:
在 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所建议的那样,数据库中的小数点应以“.”而不是“,”分隔。
答:
尝试
@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,即可获得接近的值。您可能需要调整舍入以适应。
查看存储的实际数据,通过应用程序检查,然后
最初的行是:-
最后一行是:-
-0.20 标记周围的行是:-
- 突出显示提取的行
其他(在提供实体和实际数据后)
问题 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,',');"
- 这假定两列应包含相同的值。
评论
@Entity
评论