sql >> データベース >  >> RDS >> SQLite

ルーム-外部SQLiteと内部DBの使用

    必要なもの:

    保存されているパスを変更せずに、外部データベースを内部Room-Databaseにアタッチできるようにする必要があります。それらを追加した後、Room Entity、Dao、およびDatabaseオブジェクトでデータベースを使用できるようにする必要があります。これを達成するための可能な方法はありますか?

    別のルームデータベースインスタンスを利用できるため、アタッチしない方が簡単な場合があります。添付されたスキーマ名に対応するために、個別のDAOが必要になると思います(私は信じています)。以下の例は(私が誰かのために遊んでいたものに基づいているため、かなり紛らわしい列名に基づいています)

    例えばATTACH DATABASE .... AS otherを想定 (添付されたスキーマはその他 )(メインデータベースの場合)の代わりに

    @Query("SELECT * FROM AllUsers")
    List<AllUsers> getAllAllUsers();
    

    無料が必要です:-

    @SkipQueryVerification
    @Query("SELECT * FROM other.AllUsers")
    List<AllUsers> getOtherAllAllUsers();
    

    など

    ただし、代わりに(メイン用に)次のようなものがある場合:-

        mLPDB = Room.databaseBuilder(this,LoanPaymentDatabase.class,"mydb").allowMainThreadQueries().build();
        mLPDB_DAO = mLPDB.mDao();
    

    と一緒に(他の人のために):-

        mOtherDB = Room.databaseBuilder(this,LoanPaymentDatabase.class,OtherDatabaseHelper.DBNAME).allowMainThreadQueries().build();
        mOtherDAO = mOtherDB.mDao();
    

    その後、同じDAOを使用して両方にアクセスできます。

    • もちろん、上記はスキーマが補完的であることを前提としています(必ずしも正確ではありません)。

    必ずしも正確ではありませんか?

    コメントもカバーしています:-

    最初にデータを部屋自体に移行する必要があります。

    • 少し遊んで、移行する必要があるを回避できます。 user_versionを0に設定して、roomをだまします。この場合、Roomはバージョン番号を設定します(限定テスト)。ただし、GreenDaoまたはサーバーがこれ(宿題)をどのように処理するかはわかりません。

    • 私の限定的なテストは、INTEGER PRIMARY KEYを使用する、つまりAUTOINCREMENTを使用しない列を移行する際の一般的な問題に対するものでした。移行する場合の部屋は、スキーマの不一致について不平を言います。そのため、意図的にAUTOINCREMENTをコーディングせず、user_versionを0に設定し、Roomを介してデータベースにアクセスする際の苦情はありませんでした。 rumplestilskinの列タイプも使用しました 苦情はありません。

    そのため、user_versionを0に設定することで、恐ろしい期待/検出の移行の問題を回避できると思います(したがって、移行を回避できると思います)。明らかに、列名はエ​​ンティティで定義され、無視されない場合は一致する必要があります。

    • エンティティが定義されていない列を追加しようとしましたが、上記の結果を使用しても苦情はありません(これらのテストは以下のコードで明らかです)。

    以下は、2エンティティルームデータベースの例であり、その他をテストするためのものです。 使用できるように部屋のデータベースと十分に一致する、つまりエンティティの列名が一致する、部屋の外に構築されたデータベース。

    他のデータベース

    他の部屋以外のデータベースは、 SQLiteOpenHelperを介して作成されます OtherDatabaseHelper.javaによるサブクラス :-

    public class OtherDatabaseHelper extends SQLiteOpenHelper {
    
        public static final String DBNAME = "lpolddb";
        public static final int DBVERSION = 1;
        public static final String ALLUSERS_TBL = "AllUsers";
        public static final String PAIDUNPAID_TBL = "PaidUnpaid";
    
        /*
            @PrimaryKey(autoGenerate = true)
            private long auid;
            private String Name;
            private int Loan;
            private int TimeInMonths;
         */
        public static final String ALLUSERS_COL_AUID = "auid";
        public static final String ALLUSERS_COL_NAME = "Name";
        public static final String ALLUSERS_COL_LOAN = "Loan";
        public static final String ALLUSERS_COL_TIMEINMONTHS = "TimeInMonths";
    
        private static final String crt_allusers_table_sql =
                "CREATE TABLE IF NOT EXISTS " + ALLUSERS_TBL + "(" +
                        //ALLUSERS_COL_AUID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
                        ALLUSERS_COL_AUID + " INTEGER PRIMARY KEY," +
                        ALLUSERS_COL_NAME + " TEXT, " +
                        ALLUSERS_COL_LOAN + " INTEGER, " +
                        "someothercolumnnotdefineinroom TEXT, " + //!!!!!!!!!! not a column in an entity
                        ALLUSERS_COL_TIMEINMONTHS + " INTEGER" +
                        ")";
    
        /*
            @PrimaryKey(autoGenerate = true)
            private long puid;
            private int TimeInMonths;
            private String PaidUnpaid;
            @ForeignKey(
                entity = AllUsers.class,
                parentColumns = {"auid"},
                childColumns = {"AllUsersReference"},
                onUpdate = ForeignKey.CASCADE, onDelete = ForeignKey.CASCADE)
            private long AllUsersReference;
         */
    
        public static final String PAIDUNPAID_COL_PUID = "puid";
        public static final String PAIDUNPAID_TIMEINMONTHS = ALLUSERS_COL_TIMEINMONTHS;
        public static final String PAIDUNPAID_COL_PAIDUNPAID = "PaidUnpaid";
        public static final String PAIDUNPAID_COL_ALLUSERSREFERENCE = "AllUsersReference";
    
        public static final String crt_paidunpaid_table_sql =
                "CREATE TABLE IF NOT EXISTS " + PAIDUNPAID_TBL + "(" +
                        PAIDUNPAID_COL_PUID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
                        PAIDUNPAID_TIMEINMONTHS + " rumplestilskin, " + // !!!!!!!!!!!
                        PAIDUNPAID_COL_PAIDUNPAID + " TEXT," +
                        PAIDUNPAID_COL_ALLUSERSREFERENCE + " INTEGER " +
                        " REFERENCES " + ALLUSERS_TBL + "(" + ALLUSERS_COL_AUID + ") " +
                        "ON UPDATE CASCADE ON DELETE CASCADE" +
                        ")";
    
    
        SQLiteDatabase mDB;
        public OtherDatabaseHelper(Context context) {
            super(context, DBNAME, null, DBVERSION);
            mDB = this.getWritableDatabase();
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(crt_allusers_table_sql);
            db.execSQL(crt_paidunpaid_table_sql);
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
        }
    
        public long insertAllUsers(String name, int loanamount, int periodofloan) {
            ContentValues cv = new ContentValues();
            cv.put(ALLUSERS_COL_NAME,name);
            cv.put(ALLUSERS_COL_LOAN,loanamount);
            cv.put(ALLUSERS_COL_TIMEINMONTHS,periodofloan);
            return mDB.insert(ALLUSERS_TBL,null,cv);
        }
    
        public long insertPaidUnpaid(int formonth, String status, long allUserreferenced) {
            ContentValues cv = new ContentValues();
            cv.put(PAIDUNPAID_TIMEINMONTHS,formonth);
            cv.put(PAIDUNPAID_COL_PAIDUNPAID,status);
            cv.put(PAIDUNPAID_COL_ALLUSERSREFERENCE,allUserreferenced);
            return mDB.insert(PAIDUNPAID_TBL,null,cv);
        }
    }
    
    • 奇妙な/意図的に追加された不一致についてのコメントを参照してください
    • これは人口が多く、代替のRoomデータベースから、および MainActivity.javaの接続されたDBを介してアクセスされます。 以下

    部屋のデータベース

    2つのエンティティ:-

    AllUsers.java

    @Entity
    public class AllUsers {
        @PrimaryKey(autoGenerate = true)
        private long auid;
        private String Name;
        private int Loan;
        private int TimeInMonths;
    
        public AllUsers() {
        }
    
        @Ignore
        public AllUsers(String Name, int Loan, int TimeInMonths) {
            this.Name = Name;
            this.Loan = Loan;
            this.TimeInMonths = TimeInMonths;
        }
    
        public long getAuid() {
            return auid;
        }
    
        public void setAuid(long auid) {
            this.auid = auid;
        }
    
        public String getName() {
            return Name;
        }
    
        public void setName(String name) {
            Name = name;
        }
    
        public int getLoan() {
            return Loan;
        }
    
        public void setLoan(int loan) {
            Loan = loan;
        }
    
        public int getTimeInMonths() {
            return TimeInMonths;
        }
    
        public void setTimeInMonths(int timeInMonths) {
            TimeInMonths = timeInMonths;
        }
    }
    

    およびPaidUnpaid.java :-

    @Entity
    public class PaidUnpaid {
        @PrimaryKey(autoGenerate = true)
        private long puid;
        private int TimeInMonths;
        private String PaidUnpaid;
        @ForeignKey(
                entity = AllUsers.class,
                parentColumns = {"auid"},
                childColumns = {"AllUsersReference"},
                onUpdate = ForeignKey.CASCADE, onDelete = ForeignKey.CASCADE)
        private long AllUsersReference;
    
    
        public PaidUnpaid() {
        }
    
        @Ignore
        public PaidUnpaid(int TimeInMonths, String PaidUnpaid, long AllUsersreference) {
            this.TimeInMonths = TimeInMonths;
            this.PaidUnpaid = PaidUnpaid;
            this.AllUsersReference = AllUsersreference;
        }
    
        public long getPuid() {
            return puid;
        }
    
        public void setPuid(long puid) {
            this.puid = puid;
        }
    
        public int getTimeInMonths() {
            return TimeInMonths;
        }
    
        public void setTimeInMonths(int timeInMonths) {
            TimeInMonths = timeInMonths;
        }
    
        public String getPaidUnpaid() {
            return PaidUnpaid;
        }
    
        public void setPaidUnpaid(String paidUnpaid) {
            PaidUnpaid = paidUnpaid;
        }
    
        public long getAllUsersReference() {
            return AllUsersReference;
        }
    
        public void setAllUsersReference(long allUsersReference) {
            AllUsersReference = allUsersReference;
        }
    }
    

    追加のPOJOクラス、 AllUsersAndPaidUnpaidsList.java それはそのように組み込まれて使用されて遊んでいました:-

    public class AllUsersAndPaidUnpaidsList {
    
        @Embedded
        AllUsers allUsers;
        @Ignore
        @PrimaryKey
        long auid;
    
        @Ignore
        @Relation(entity = PaidUnpaid.class,parentColumn = "auid",entityColumn = "puid")
        List<PaidUnpaid> paidUnpaidList;
    
        @Ignore
        public AllUsersAndPaidUnpaidsList(AllUsers au, List<PaidUnpaid> pulist) {
            this.allUsers = au;
            this.paidUnpaidList = pulist;
        }
    
        public List<PaidUnpaid> getPaidUnpaidList() {
            return this.paidUnpaidList;
        }
    
    
        public void setPaidUnpaidList(List<PaidUnpaid> paidUnpaidList) {
            this.paidUnpaidList = paidUnpaidList;
        }
    
        public AllUsers getAllUsers() {
            return allUsers;
        }
    
        public void setAllUsers(AllUsers allUsers) {
            this.allUsers = allUsers;
        }
    
        public void outputToLog(String tag) {
            StringBuilder sb = new StringBuilder("AllUsersName = ")
                    .append(this.allUsers.getName())
                    .append(" TimeInMonths = ")
                    .append(String.valueOf(this.allUsers.getTimeInMonths()))
                    ;
            for (PaidUnpaid pu: this.getPaidUnpaidList()) {
                sb.append("\n\t TimeInMonths = ")
                        .append(String.valueOf(pu.getTimeInMonths()))
                        .append(" Paid/Unpaid = ")
                        .append(pu.getPaidUnpaid());
            }
            Log.d(tag,sb.toString());
        }
    }
    

    単一のインターフェースDao.java :-

    @androidx.room.Dao
    public interface Dao {
    
        @Insert(onConflict = OnConflictStrategy.IGNORE)
        long[] insertAllUsers(AllUsers... allUsers);
    
        @Insert(onConflict = OnConflictStrategy.IGNORE)
        long insertAllUsers(AllUsers allUsers);
    
        @Insert(onConflict = OnConflictStrategy.IGNORE)
        long[] insertPaidUnpaid(PaidUnpaid... paidUnpaids);
    
        @Insert(onConflict = OnConflictStrategy.IGNORE)
        long insertPaidUnpaid(PaidUnpaid paidUnpaid);
    
        @Update(onConflict = OnConflictStrategy.IGNORE)
        int updateAllUsers(AllUsers... allUsers);
    
        @Update(onConflict =  OnConflictStrategy.IGNORE)
        int updateAllUsers(AllUsers allUsers);
    
        @Update(onConflict = OnConflictStrategy.IGNORE)
        int updatePaidUnpaid(PaidUnpaid... paidUnpaids);
    
        @Update(onConflict = OnConflictStrategy.IGNORE)
        int updatePaidUnpaid(PaidUnpaid paidUnpaid);
    
        @Delete
        int deleteAllUsers(AllUsers... allUsers);
    
        @Delete
        int deleteAllUsers(AllUsers allUsers);
    
        @Delete
        int deletePaidUnpaid(PaidUnpaid... paidUnpaids);
    
        @Delete
        int deletePaidUnpaid(PaidUnpaid paidUnpaid);
    
        @Query("SELECT * FROM AllUsers")
        List<AllUsers> getAllAllUsers();
    
        @Query("SELECT * FROM AllUsers WHERE auid = :id")
        List<AllUsers> getOneAllUsersById(long id);
    
        @Query("SELECT * FROM PaidUnpaid")
        List<PaidUnpaid> getAllPaidUnpaids();
    
        @Query("SELECT * FROM PaidUnpaid WHERE puid = :id")
        List<PaidUnpaid> getOnePaidUnpaidById(long id);
    
        @Query("SELECT * FROM PaidUnpaid WHERE AllUsersReference = :allUsersid")
        List<PaidUnpaid> getPaidUnpaidsForAllUsersId(long allUsersid);
    
        /*************
         * Some Additional DAO's for attached not required for alternative helper
         * in practice you would likely need attached versions of all
         ************/
    
        @Query("SELECT * FROM other.PaidUnpaid WHERE AllUsersReference = :allUsersid")
        @SkipQueryVerification
        List<PaidUnpaid> getOtherPaidUnpaidForAllUsersId(long allUsersid);
    
        @SkipQueryVerification
        @Query("SELECT * FROM other.AllUsers")
        List<AllUsers> getOtherAllAllUsers();
    }
    

    ルームデータベースクラスLoanPaymentDatabase.java

    @Database(entities = {AllUsers.class,PaidUnpaid.class},exportSchema = false,version = 1)
    public abstract class LoanPaymentDatabase extends RoomDatabase {
        public abstract Dao mDao();
    }
    

    すべてをまとめる

    最後に:-

    1. その他を作成してデータを入力します テスト用の(部屋以外の)データベース(存在しない場合)。 user_version(Androidトークのデータベースバージョン)を0に設定します。

    2. 必要に応じて、データベースのRoomバージョンを作成します。

    3. Roomバージョンに2行追加します。
    4. ルームバージョンのデータをログに出力します。
    5. その他を使用して代替のRoomDatabaseを作成します データベース。
    6. その他のデータを出力します Room経由のデータベース。
    7. その他を添付します データベースをRoomバージョンに変換します。
    8. 接続されたその他にアクセスする元のRoomdatabaseを介して両方からデータを出力します other。????を含む追加のDAOインターフェイスを介したデータベース 。

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
    
        LoanPaymentDatabase mLPDB;
        Dao mLPDB_DAO;
    
        LoanPaymentDatabase mOtherDB;
        Dao mOtherDAO;
        Random rnd = new Random();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            manageOtherDatabase();
    
            mLPDB = Room.databaseBuilder(this,LoanPaymentDatabase.class,"mydb").allowMainThreadQueries().build();
            mLPDB_DAO = mLPDB.mDao();
            // Add some(2) AllUsers
            mLPDB_DAO.insertAllUsers(new AllUsers("Fred",5000,5));
            mLPDB_DAO.insertAllUsers(new AllUsers("Mary", 4000,6));
    
            // Add Some PaidUnpaid's for each AllUsers
            // Random amount with random paid or unpaid
            // This is just for demonstration and doesn't reflect what would typically be done
            List<AllUsers> allusers =  mLPDB_DAO.getAllAllUsers();
            for (AllUsers au: allusers) {
                int lc = rnd.nextInt(4) + 1;
                int month = 1;
                for (int i=0; i < lc; i++) {
                    String paid = "Paid";
                    if((rnd.nextInt(2) % 2) > 0 ) {
                        paid = "Unpaid";
                    }
                    mLPDB_DAO.insertPaidUnpaid(new PaidUnpaid(month++, paid, au.getAuid()));
                }
            }
    
            //Extract all AllUsersAndPaidUnpaid (i.e  each AllUsers with the related PaidUnpaid for the AllUsers)
            ArrayList<AllUsersAndPaidUnpaidsList> aupulist = new ArrayList<>();
            for (AllUsers au: allusers) {
                List<PaidUnpaid> pulist = mLPDB_DAO.getPaidUnpaidsForAllUsersId(au.getAuid());
                aupulist.add(new AllUsersAndPaidUnpaidsList(au,pulist));
            }
    
            // Output the results
            for (AllUsersAndPaidUnpaidsList aupu: aupulist) {
                aupu.outputToLog("INITALAUPU");
            }
    
            //Use separate openHelper rather than ATTACH
            mOtherDB = Room.databaseBuilder(this,LoanPaymentDatabase.class,OtherDatabaseHelper.DBNAME).allowMainThreadQueries().build();
            mOtherDAO = mOtherDB.mDao();
            ArrayList<AllUsersAndPaidUnpaidsList> otheraupulist = new ArrayList<>();
            for (AllUsers oau: mOtherDAO.getAllAllUsers() ) {
                otheraupulist.add(new AllUsersAndPaidUnpaidsList(oau,mOtherDAO.getPaidUnpaidsForAllUsersId(oau.getAuid())));
            }
            for (AllUsersAndPaidUnpaidsList aupu: otheraupulist) {
                aupu.outputToLog("ALTDBAUPU");
            }
    
            // User Attach
            SupportSQLiteDatabase main_sdb = mLPDB.getOpenHelper().getWritableDatabase();
            SupportSQLiteDatabase other_sdb = mOtherDB.getOpenHelper().getWritableDatabase();
            main_sdb.execSQL("ATTACH DATABASE '" + other_sdb.getPath() + "' AS other");
            ArrayList<AllUsersAndPaidUnpaidsList> attachaupulist = new ArrayList<>();
            for (AllUsers aau: mLPDB_DAO.getAllAllUsers()) {
                attachaupulist.add(new AllUsersAndPaidUnpaidsList(aau,mLPDB_DAO.getPaidUnpaidsForAllUsersId(aau.getAuid())));
            }
            for (AllUsers aauother: mLPDB_DAO.getOtherAllAllUsers()) {
                attachaupulist.add(new AllUsersAndPaidUnpaidsList(aauother,mLPDB_DAO.getOtherPaidUnpaidForAllUsersId(aauother.getAuid())));
            }
            for (AllUsersAndPaidUnpaidsList aupu: attachaupulist) {
                aupu.outputToLog("ATTACHEDAUPU");
            }
    
            mLPDB.close();
        }
    
        /*********
         *  For testing purposes - Populate the OTHER database to be used
         *********/
        private void manageOtherDatabase() {
            OtherDatabaseHelper mODBHlpr = new OtherDatabaseHelper(this);
            SQLiteDatabase db = mODBHlpr.getWritableDatabase();
            db.execSQL("PRAGMA user_version = 0");
            if (DatabaseUtils.queryNumEntries(db,OtherDatabaseHelper.ALLUSERS_TBL) > 0) {
                db.close();
                mODBHlpr.close();
                return;
            }
            db.beginTransaction();
            for (int i= 0; i < 5; i++) {
                long auid = mODBHlpr.insertAllUsers("AU" + String.valueOf(i),10000 + 1,5 + i);
                for(int ii = 0; ii < 5; ii++) {
                    mODBHlpr.insertPaidUnpaid(ii,"Paid",auid);
                }
            }
            db.setTransactionSuccessful();
            db.endTransaction();
            db.close();
            mODBHlpr.close();
        }
    }
    



    1. 集計関数SUMを使用してレコードをフィルタリングする方法

    2. PostgreSQL:Unixエポックから現在までに変換する方法は?

    3. SQLのみを使用した基数36から基数10への変換

    4. 整数の除算は0を返します