android left join query with room

时间:2017-12-18 06:37:49

标签: android database android-room kotlin-android-extensions

I am trying to change my sqlite database with room library. I am little confuse with left join query.

I have implemented it with sqlite, but don't know how can I achieve same withh room?

Here is my table creation:

first table: 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))")

second table: 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)")

What I am doing is I am storing notification in notification table but its name and description will be stored with specific language, in notification_trans.

Query to achieve

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)

Question

How can I achieve same with room?

Edit

My application is multi-language application, where I am getting notification title with specific language, like Hindi or Gujarati. I am storing notification details in notification table, while title in notification_trans.

NotificationTrans have column with id, english, hindi, gujarati.

When user asked for gujarati, I am retriving notification title from notificationTrans's column gujarati.

I am able do so, in sqlite.

But now I want it with Room

2 个答案:

答案 0 :(得分: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();

}
`

我未在Link here找到的查询中进行了更改。由于您的查询很复杂,但是,它会为您提供有关如何执行此操作的建议。 在此之后,您只需要从您的Database类对象访问您的Dao接口,该对象将处理创建&所有其他的东西,如下面的这个`

@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来了解房间与房间之间的关系。实现您的要求,

编辑1: 这就是你的DAO应该是什么样的,“

@Insert
void insert(Notifications object);

//这将插入单个项目

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

虽然这可以输入数据列表,

如果您拨打AppDatabase.getAppDatabase(context).notificationDao().yourQueryMethodName()&传递你需要存储在数据库中的对象,它会做,

对于例如yourQueryMethod() 这是我在ParcelDao中插入数据的方式,db是数据库对象,& parcel是需要存储的数据对象。还有一件事,你不能在主线程上调用这个方法,所以你可能需要使用Handler或AsyncTask这个目的,抱歉,我忘记提及了。 请查看会议室Training at Android Developers以实现会议室的基本功能

答案 1 :(得分:0)

#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
}