Android中使用Room进行左连接查询

4

我正在尝试使用Room库更改我的SQLite数据库。我对左连接查询有些困惑。

我已经在SQLite中实现了它,但不知道如何在Room中实现相同的功能?

这是我的表创建:

第一个表:通知(Notification)

db.execSQL("CREATE TABLE IF NOT EXISTS $TABLE_NAME ($COLUMN_ID INTEGER PRIMARY KEY, $ICON TEXT, $TITLE INTEGER," +
                " $DATE INTEGER, $TYPE INTEGER,$URL TEXT, $MESSAGE INTEGER, FOREIGN KEY($TITLE) REFERENCES ${TableNotificationsTrans.getTableName(this)}(id)," +
                "FOREIGN KEY($MESSAGE) REFERENCES ${TableNotificationsTrans.getTableName(this)}(id))")

第二个表格:Notification_Trans
db.execSQL("CREATE TABLE IF NOT EXISTS $TABLE_NAME ($COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COLUMN_EN TEXT, $COLUMN_GU TEXT, $COLUMN_HI TEXT)")

我正在将通知存储在 notification 表中,但它的名称和描述将使用特定语言存储在 notification_trans 中。 实现查询:
DatabaseHelper.database!!.rawQuery("SELECT A.$COLUMN_ID, A.$ICON, N.${language.toLowerCase()} $TITLE, A.$DATE, A.$TYPE, A.$URL, M.${language.toLowerCase()} $MESSAGE FROM $TABLE_NAME A LEFT JOIN NotificationsTrans N ON A.$TITLE = N.id LEFT JOIN NotificationsTrans M ON A.$MESSAGE = M.id ORDER BY $DATE DESC LIMIT $pageNum*10, 10", null)

非常感谢您的信任,我将尽力完成您的翻译需求。请提供需要翻译的内容。
How can I achieve same with room?

编辑

我的应用是多语言应用程序,我会以特定语言(如印地语或古吉拉特语)获取通知标题。我将通知详细信息存储在notification表中,而标题存储在notification_trans中。

NotificationTrans具有id、英语、印地语和古吉拉特语列。

当用户要求古吉拉特语时,我从notificationTrans的gujarati列中检索通知标题。

我能够在sqlite中实现这一点。

但现在我想使用Room。


1
如果您有一个静态查询,您可以在Room中使用它的方式与SQLite完全相同。在您的情况下,您正在使用字符串插值生成查询,在这种情况下,Room无法帮助您。 - CommonsWare
2个回答

1

首先,您需要为两个模型类创建,如果已经声明了它们,您只需要进行一些更改即可。

   @Entity
public class Notification {
    @PrimaryKey
    int id;
    String icon;
    @ForeignKey(entity = Notification_Trans.class, parentColumns = "col_id", childColumns = "id")
    String title;
    int date;
    int type;
    String url;
    int msg;

}

    @Entity
public class Notification_Trans {
    @PrimaryKey(autoGenerate = true)
    int col_id;
    String column_en;
    String column_gu;
    String column_hi;

这是针对您的POJO进行的操作。我无法理解您的外键约束,敬请见谅。您可以根据需要进行更改。 您可以按照以下方式声明DAO: @Dao
public interface DAO {

    @Query("SELECT note.id, note.title, note.description, category.name as categoryName " +
            "FROM note " +
            "LEFT JOIN category ON note.category_id = category.id")
    List getCategoryNotes();

}
`

我没有修改在此处链接找到的查询。由于您的查询比较复杂,但是它会让您了解如何操作。 接下来,您只需要从数据库类对象中访问您的Dao接口,它将处理创建和所有其他room相关的事情,就像下面这个例子一样。
@Database(entities = {Notification.class, NotificationTrans.class}, version = 3)
public abstract class AppDatabase extends RoomDatabase {

    private static AppDatabase instance;

    public static AppDatabase getAppDatabase(Context context) {
        if (instance == null) {
            instance =
                    Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "database_name")
                            // allow queries on the main thread.
                            // Don't do this on a real app! See PersistenceBasicSample for an example.
                            //.allowMainThreadQueries()
                            .fallbackToDestructiveMigration()
                            .build();
        }
        return instance;
    }

    public static void destroyInstance() {

        instance = null;
    }

    public abstract Dao notificationDao();

为数据库创建一个单独的类,并跟踪其中的对象会有所帮助。您可以使用AppDatabase.getAppDatabase(context).notificationDao().yourQueryMethodName();访问数据。

您可能需要参考this以了解Room之间的关系并实现您的要求。

编辑1: 以下是DAO的示例:

@Insert
void insert(Notifications object);

//这将插入一个单独的项目

 @Insert
 void insertAll(Notifications... objects);

虽然这可以输入数据列表,但是您可以使用您的数据库对象调用此方法,例如AppDatabase.getAppDatabase(context).notificationDao().yourQueryMethodName(),而不是yourQueryMethod()。如果您调用insert()并传递要存储在数据库中的对象,则会执行此操作。
例如:db.parcelDao().insert(parcel); 这就是我如何在ParcelDao中插入数据,其中db是数据库对象,而parcel是需要存储的数据对象。还有一件事,您不能在主线程上调用此方法,因此您可能需要使用Handler或AsyncTask来完成此操作。抱歉我忘记提到了。请参阅Room Android Developers的培训,以实现基本的Room功能。

请提供详细回答。如何插入? - Lalit Jadav
让我知道你不理解的部分,我会尝试详细说明。 - Ganesh
我该如何将值插入到数据库中? - Lalit Jadav
不会插入到翻译表中。 - Lalit Jadav
如果我可以插话,我认为他想表达的是:您正在尝试向一个表中插入数据,但具有外键和其他属性的表,该如何将数据插入其中?我们不能自动完成吗?因为定义外部约束有什么用处,如果我们必须手动执行它。 - Kashif K.
显示剩余5条评论

1

#1 - 需要创建一个模型类,与查询结果相匹配

data class ClientAndCity(
     @ColumnInfo(name="id") val id: Long,
     @ColumnInfo(name="client_name") val clientName: String?,
     @ColumnInfo(name="city_name") val cityName: String?
)

#2 - 在你的DAO中创建查询

@Query("SELECT clients.id, clients.name AS client_name, cities.name AS city_name FROM clients LEFT JOIN cities ON cities.id = clients.city_id WHERE clientes.id = :clientId")
fun getClientAndHisCity(clientId: Long): ClientAndCity?

#3 - 使用您的函数

CoroutineScope(Dispatchers.IO).launch{
     val result: ClientAndCity = clientDAO.getClientAndHisCity(clientId)
     //do something with it
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接