如何在房间数据库dao中附加两个或多个子查询,而这些子查询存储在变量中
Posted
技术标签:
【中文标题】如何在房间数据库dao中附加两个或多个子查询,而这些子查询存储在变量中【英文标题】:How to attach two or more sub queries in room database dao while those subQuery stored in variables 【发布时间】:2021-11-15 07:13:15 【问题描述】:我正在将我的旧数据库升级到房间数据库,同时从普通 sql 语句转换为房间 sql 语句。 我面临以下情况的问题。
场景一: 我已经将子查询存储在这样的变量中
String subQueryLocalAddress = "SELECT * FROM localAddressTable where activeAddressId = 1";
String subQueryPermanentAddress = "SELECT * FROM permanentAddressTable where activeAddressId = 1";
现在,这将是有条件的,就像那样。
public Cursor loadAllUserAdress(boolean isLocal)
String userAddressQuery = "SELECT * FROM userTable Where "
+ isLocal? subQueryLocalAddress : subQueryPermanentAddress;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(userAddressQuery, null);
return cursor;
场景二: 我有一堆像这样的常量的过滤器
Constant.ORDER_BY_FIRST_NAME_DESC = "ORDER BY firstName DESC";
Constant.ORDER_BY_LAST_NAME_DESC = "ORDER BY lastName DESC";
现在,这个标志设置在 UI 级别,它会根据各自的标志检查数据库类 我的查询将返回受尊重的数据。
public Cursor loadAllUserDetails()
String userDetailsQuery = "SELECT * FROM userTable Where " + Constant.ORDER_BY_LAST_NAME_DESC;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(userDetailsQuery, null);
return cursor;
我想在单个变量中组合或合并两个或多个子查询,然后触发它。我有动态查询。
【问题讨论】:
【参考方案1】:简而言之,使用 @Rawquery 注释进行动态查询。
演示
这是一个前后 Room 演示,它使用了一个简单的表 TableX,其中包含 id (long/INTEGER PRIMARY KEY)、firstname (String/TEXT) 和 lastName (String/TEXT)。
演示插入一些数据,然后通过动态生成的 SQL 排序提取数据(场景二)。
在房间 TableX 嵌入到 DBHelper 之前,带有名称常量和所有 ORDER BY 排列,还有一些方法,所以 DBHelper :-
class DBHelper extends SQLiteOpenHelper
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
private static volatile DBHelper instance = null;
SQLiteDatabase db;
private DBHelper(Context context)
super(context,DBNAME,null,DBVERSION);
db = this.getWritableDatabase();
public static DBHelper getInstance(Context context)
if (instance == null)
instance = new DBHelper(context);
return instance;
@Override
public void onCreate(SQLiteDatabase db)
db.execSQL(TableX.createSQL);
db.execSQL(TableX.createFirstNameIndex);
db.execSQL(TableX.createLastNameIndex);
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1)
public long insert(String firstName, String lastName)
ContentValues cv = new ContentValues();
cv.put(TableX.COLUMN_FIRSTNAME,firstName);
cv.put(TableX.COLUMN_LASTNAME,lastName);
return db.insert(TableX.NAME,null,cv);
public Cursor loadAllDetails(int orderBy)
StringBuilder sb = new StringBuilder("SELECT * FROM ").append(NAME);
switch (orderBy)
case TableX.FIRSTNAME_DESCENDING:
sb.append(TableX.ORDER_BY_FIRSTNAME_DESC);
break;
case TableX.FIRSTNAME_ASCENDING:
sb.append(TableX.ORDER_BY_FIRSTNAME_ASC);
break;
case TableX.LASTNAME_DESCENDING:
sb.append(TableX.ORDER_BY_LASTNAME_DESC);
break;
case TableX.LASTNAME_ASCENDING:
sb.append(TableX.ORDER_BY_LASTNAME_ASC);
break;
default:
break;
sb.append(";");
return db.rawQuery(sb.toString(),null);
class TableX
public static final String NAME = "tablex";
public static final String COLUMN_ID = BaseColumns._ID;
public static final String COLUMN_FIRSTNAME = "firstName";
public static final String COLUMN_LASTNAME = "lastName";
public static final String ORDER_BY_FIRSTNAME = " ORDER BY " + COLUMN_FIRSTNAME;
public static final String ORDER_BY_LASTNAME = " ORDER BY " + COLUMN_LASTNAME;
public static final String ORDER_BY_FIRSTNAME_DESC = ORDER_BY_FIRSTNAME + " DESC";
public static final String ORDER_BY_FIRSTNAME_ASC = ORDER_BY_FIRSTNAME + " ASC";
public static final String ORDER_BY_LASTNAME_DESC = ORDER_BY_LASTNAME + " DESC";
public static final String ORDER_BY_LASTNAME_ASC = ORDER_BY_LASTNAME + " ASC";
public static final int FIRSTNAME_DESCENDING = 0;
public static final int FIRSTNAME_ASCENDING = 1;
public static final int LASTNAME_DESCENDING = 2;
public static final int LASTNAME_ASCENDING = 3;
private static final String createSQL = "CREATE TABLE IF NOT EXISTS " + NAME + "(" +
COLUMN_ID + " INTEGER PRIMARY KEY"
+ "," + COLUMN_FIRSTNAME + " TEXT"
+ "," + COLUMN_LASTNAME + " TEXT"
+ ")";
private static final String createFirstNameIndex = "CREATE INDEX IF NOT EXISTS IDX_" + NAME + COLUMN_FIRSTNAME
+ " ON " + NAME + "("
+ COLUMN_FIRSTNAME
+ ")";
private static final String createLastNameIndex = "CREATE INDEX IF NOT EXISTS IDX" + NAME + COLUMN_LASTNAME
+ " ON " + NAME + "("
+ COLUMN_LASTNAME
+ ")";
public Cursor getSomeData(String query)
return db.rawQuery(query,null);
相当于房间
首先是@Entity 类TableXEntity:-
@Entity(tableName = DBHelper.TableX.NAME,
indices =
@Index(value = DBHelper.TableX.COLUMN_FIRSTNAME),
@Index(value = DBHelper.TableX.COLUMN_LASTNAME)
)
class TableXEntity
@PrimaryKey @ColumnInfo(name = DBHelper.TableX.COLUMN_ID)
Long id;
@ColumnInfo(name = DBHelper.TableX.COLUMN_FIRSTNAME)
String firstName;
@ColumnInfo(name = DBHelper.TableX.COLUMN_LASTNAME)
String lastName;
public TableXEntity()
@Ignore
public TableXEntity(String firstName, String lastName)
this.firstName = firstName;
this.lastName = lastName;
冒昧地使用了房间前常量
除了@Ignored 第二个构造函数之外没有什么特别的地方
@Dao 类 TableXDao :-
@Dao
abstract class TableXDao
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(TableXEntity tableXEntity);
@Query("SELECT * FROM " + DBHelper.TableX.NAME + DBHelper.TableX.ORDER_BY_FIRSTNAME_ASC)
abstract List<TableXEntity> getAllByFirstNameAscending();
// etc
/* cannot use the @Query below and commented out, as compile error
error: extraneous input ':order' expecting
<EOF>, ';', K_ALTER, K_ANALYZE, K_ATTACH, K_BEGIN, K_COMMIT, K_CREATE, K_DELETE, K_DETACH,
K_DROP, K_END, K_EXPLAIN, K_INSERT, K_PRAGMA, K_REINDEX, K_RELEASE, K_REPLACE, K_ROLLBACK, K_SAVEPOINT,
K_SELECT, K_UPDATE, K_VACUUM, K_VALUES, K_WITH, UNEXPECTED_CHAR
abstract List<TableXEntity> getAllByPassedOrder(String order);
Plus it wraps passed parameter in '' so is taken as a literal not an ORDER BY clause
*/
//@SkipQueryVerification
//@Query("SELECT * FROM " + DBHelper.TableX.NAME + " :order")
//abstract List<TableXEntity> getAllByPassedOrder(String order);
/* SO */
@RawQuery
abstract List<TableXEntity> rawq(SupportSQLiteQuery qry);
请注意,假设是房间,所以没有光标,而是对象数组。
@Database 类 TheDatabase(注意不同的数据库名称,以便两者可以共存以进行演示):-
@Database(entities = TableXEntity.class,version = 1)
abstract class TheDatabase extends RoomDatabase
abstract TableXDao getTableXDao();
private static volatile TheDatabase instance = null;
public static TheDatabase getInstance(Context context)
if (instance == null)
instance = Room.databaseBuilder(
context, TheDatabase.class,"myroomdb"
)
.allowMainThreadQueries()
.build();
return instance;
将两者付诸行动的是 MainActivity :-
public class MainActivity extends AppCompatActivity
DBHelper dbHelper;
TheDatabase roomDB;
TableXDao roomDao;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = DBHelper.getInstance(this);
dbHelper.insert("Mary","Bloggs");
dbHelper.insert("Francis","Frank");
dbHelper.insert("Jane","Doe");
logIt(dbHelper.loadAllDetails(DBHelper.TableX.LASTNAME_ASCENDING));
logIt(dbHelper.loadAllDetails(DBHelper.TableX.FIRSTNAME_ASCENDING));
logIt(dbHelper.loadAllDetails(DBHelper.TableX.LASTNAME_DESCENDING));
/* Room */
roomDB = TheDatabase.getInstance(this);
roomDao = roomDB.getTableXDao();
roomDao.insert(new TableXEntity("Mary","Bloggs"));
roomDao.insert(new TableXEntity("Francis","Frank"));
roomDao.insert(new TableXEntity("Jane","Doe"));
roomLogit(roomDao.getAllByFirstNameAscending());
roomLogit(getListByPassedOrder(DBHelper.TableX.FIRSTNAME_DESCENDING));
roomLogit(getListByPassedOrder(DBHelper.TableX.FIRSTNAME_ASCENDING));
roomLogit(getListByPassedOrder(DBHelper.TableX.LASTNAME_DESCENDING));
roomLogit(getListByPassedOrder(DBHelper.TableX.LASTNAME_ASCENDING));
void logIt(Cursor c)
DatabaseUtils.dumpCursor(c);
void roomLogit(List<TableXEntity> thelist)
for (TableXEntity t: thelist)
Log.d("ROOMINFO","ID is " + t.id + " FirstName is " + t.firstName + " LastName is " + t.lastName);
private List<TableXEntity> getListByPassedOrder(int order)
StringBuilder sb = new StringBuilder("SELECT * FROM ").append(DBHelper.TableX.NAME);
switch (order)
case DBHelper.TableX.FIRSTNAME_DESCENDING:
sb.append(DBHelper.TableX.ORDER_BY_FIRSTNAME_DESC);
break;
case DBHelper.TableX.FIRSTNAME_ASCENDING:
sb.append(DBHelper.TableX.ORDER_BY_FIRSTNAME_ASC);
break;
case DBHelper.TableX.LASTNAME_DESCENDING:
sb.append(DBHelper.TableX.ORDER_BY_LASTNAME_DESC);
break;
case DBHelper.TableX.LASTNAME_ASCENDING:
sb.append(DBHelper.TableX.ORDER_BY_LASTNAME_ASC);
break;
default:
break;
sb.append(";");
return roomDao.rawq(new SimpleSQLiteQuery(sb.toString(),null));
首先填充房间前数据库,并使用各种动态生成的排序提取数据,然后将光标转储到日志中。
然后房间数据库基本上模仿上述但显然使用房间,数据输出到日志虽然是通过提取的对象(TableXEntity)完成的。
日志中的结果:-
2021-09-22 13:08:19.393 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@b9ccda0
2021-09-22 13:08:19.394 I/System.out: 0
2021-09-22 13:08:19.394 I/System.out: _id=1
2021-09-22 13:08:19.394 I/System.out: firstName=Mary
2021-09-22 13:08:19.394 I/System.out: lastName=Bloggs
2021-09-22 13:08:19.394 I/System.out:
2021-09-22 13:08:19.394 I/System.out: 1
2021-09-22 13:08:19.394 I/System.out: _id=3
2021-09-22 13:08:19.394 I/System.out: firstName=Jane
2021-09-22 13:08:19.394 I/System.out: lastName=Doe
2021-09-22 13:08:19.395 I/System.out:
2021-09-22 13:08:19.395 I/System.out: 2
2021-09-22 13:08:19.395 I/System.out: _id=2
2021-09-22 13:08:19.395 I/System.out: firstName=Francis
2021-09-22 13:08:19.395 I/System.out: lastName=Frank
2021-09-22 13:08:19.395 I/System.out:
2021-09-22 13:08:19.395 I/System.out: <<<<<
2021-09-22 13:08:19.396 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@22a7d59
2021-09-22 13:08:19.396 I/System.out: 0
2021-09-22 13:08:19.396 I/System.out: _id=2
2021-09-22 13:08:19.396 I/System.out: firstName=Francis
2021-09-22 13:08:19.397 I/System.out: lastName=Frank
2021-09-22 13:08:19.397 I/System.out:
2021-09-22 13:08:19.397 I/System.out: 1
2021-09-22 13:08:19.397 I/System.out: _id=3
2021-09-22 13:08:19.397 I/System.out: firstName=Jane
2021-09-22 13:08:19.397 I/System.out: lastName=Doe
2021-09-22 13:08:19.398 I/System.out:
2021-09-22 13:08:19.398 I/System.out: 2
2021-09-22 13:08:19.398 I/System.out: _id=1
2021-09-22 13:08:19.398 I/System.out: firstName=Mary
2021-09-22 13:08:19.398 I/System.out: lastName=Bloggs
2021-09-22 13:08:19.398 I/System.out:
2021-09-22 13:08:19.398 I/System.out: <<<<<
2021-09-22 13:08:19.398 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@a1ead1e
2021-09-22 13:08:19.399 I/System.out: 0
2021-09-22 13:08:19.399 I/System.out: _id=2
2021-09-22 13:08:19.399 I/System.out: firstName=Francis
2021-09-22 13:08:19.399 I/System.out: lastName=Frank
2021-09-22 13:08:19.399 I/System.out:
2021-09-22 13:08:19.399 I/System.out: 1
2021-09-22 13:08:19.399 I/System.out: _id=3
2021-09-22 13:08:19.399 I/System.out: firstName=Jane
2021-09-22 13:08:19.400 I/System.out: lastName=Doe
2021-09-22 13:08:19.400 I/System.out:
2021-09-22 13:08:19.400 I/System.out: 2
2021-09-22 13:08:19.400 I/System.out: _id=1
2021-09-22 13:08:19.400 I/System.out: firstName=Mary
2021-09-22 13:08:19.400 I/System.out: lastName=Bloggs
2021-09-22 13:08:19.400 I/System.out:
2021-09-22 13:08:19.400 I/System.out: <<<<<
2021-09-22 13:08:19.456 D/ROOMINFO: ID is 2 FirstName is Francis LastName is Frank
2021-09-22 13:08:19.456 D/ROOMINFO: ID is 3 FirstName is Jane LastName is Doe
2021-09-22 13:08:19.456 D/ROOMINFO: ID is 1 FirstName is Mary LastName is Bloggs
2021-09-22 13:08:19.458 D/ROOMINFO: ID is 1 FirstName is Mary LastName is Bloggs
2021-09-22 13:08:19.458 D/ROOMINFO: ID is 3 FirstName is Jane LastName is Doe
2021-09-22 13:08:19.458 D/ROOMINFO: ID is 2 FirstName is Francis LastName is Frank
2021-09-22 13:08:19.460 D/ROOMINFO: ID is 2 FirstName is Francis LastName is Frank
2021-09-22 13:08:19.460 D/ROOMINFO: ID is 3 FirstName is Jane LastName is Doe
2021-09-22 13:08:19.460 D/ROOMINFO: ID is 1 FirstName is Mary LastName is Bloggs
2021-09-22 13:08:19.462 D/ROOMINFO: ID is 2 FirstName is Francis LastName is Frank
2021-09-22 13:08:19.462 D/ROOMINFO: ID is 3 FirstName is Jane LastName is Doe
2021-09-22 13:08:19.462 D/ROOMINFO: ID is 1 FirstName is Mary LastName is Bloggs
2021-09-22 13:08:19.463 D/ROOMINFO: ID is 1 FirstName is Mary LastName is Bloggs
2021-09-22 13:08:19.463 D/ROOMINFO: ID is 3 FirstName is Jane LastName is Doe
2021-09-22 13:08:19.463 D/ROOMINFO: ID is 2 FirstName is Francis LastName is Frank
【讨论】:
你好,MikeT 这是非常好的答案,我已经应用它并且它正在工作。谢谢。以上是关于如何在房间数据库dao中附加两个或多个子查询,而这些子查询存储在变量中的主要内容,如果未能解决你的问题,请参考以下文章