什么是初始迁移,在现有应用程序中设置 Room (SQLite)?
What's the initial migration, setting up Room (SQLite) in an existing app?
我正致力于在我的应用程序中设置一个小型 SQLite 数据库,该数据库到目前为止一直将数据存储在 OS MediaStore 中。我想远离它,并使用 Room。
最初的table非常简单,基本上只是一个用于描述的TEXT字段,以及MediaStore中实际图像的一些ID。但是,我也想设置其他几个 table。这看起来有点合理吗:
import android.provider.BaseColumns;
import android.provider.MediaStore;
public class AlbumContract {
public static class PhotoEntry implements BaseColumns {
public static final String TABLE_NAME = "photo";
public static final String COLUMN_NAME_IMAGE_ID = "fk_image_id";
public static final String COLUMN_NAME_IMAGE_URI = "mediastore_uri";
public static final String COLUMN_NAME_EVENT_ID = "fk_event_id";
public static final String COLUMN_NAME_STACK_ID = "fk_stack_id";
public static final String COLUMN_NAME_DESCRIPTION = "description";
}
public static class StackEntry implements BaseColumns {
public static final String TABLE_NAME = "stack";
public static final String COLUMN_NAME_STACK_LEADER = "fk_photo_id";
}
public static class EventEntry implements BaseColumns {
public static final String TABLE_NAME = "event";
public static final String COLUMN_NAME_TITLE = "title";
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
public static final String COLUMN_NAME_ALBUM_ID = "fk_album_id";
}
public static class AlbumEntry implements BaseColumns {
public static final String TABLE_NAME = "album";
public static final String COLUMN_NAME_TITLE = "title";
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
}
public static final String SQL_CREATE_PHOTO =
"CREATE TABLE " + PhotoEntry.TABLE_NAME + " (" +
PhotoEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
PhotoEntry.COLUMN_NAME_IMAGE_ID + " INTEGER, " +
PhotoEntry.COLUMN_NAME_IMAGE_URI + " TEXT, " +
PhotoEntry.COLUMN_NAME_STACK_ID + " INTEGER, " +
PhotoEntry.COLUMN_NAME_EVENT_ID + " INTEGER, " +
PhotoEntry.COLUMN_NAME_DESCRIPTION + " TEXT, " +
// Foreign key to MediaStore.Images
"FOREIGN KEY (" + PhotoEntry.COLUMN_NAME_IMAGE_ID + ") " +
"REFERENCES " + MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "(" + MediaStore.Images.Media._ID + ") " +
// Foreign key to "stack" table
"FOREIGN KEY (" + PhotoEntry.COLUMN_NAME_STACK_ID + ") " +
"REFERENCES " + StackEntry.TABLE_NAME + "(" + StackEntry._ID + ") " +
// Foreign key to "event" table
"FOREIGN KEY (" + PhotoEntry.COLUMN_NAME_EVENT_ID + ") " +
"REFERENCES " + EventEntry.TABLE_NAME + "(" + EventEntry._ID + ") " +
")";
public static final String SQL_CREATE_STACK =
"CREATE TABLE " + StackEntry.TABLE_NAME + " (" +
StackEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
StackEntry.COLUMN_NAME_STACK_LEADER + " INTEGER " +
"FOREIGN KEY (" + StackEntry.COLUMN_NAME_STACK_LEADER + ") " +
"REFERENCES " + PhotoEntry.TABLE_NAME + "(" + PhotoEntry._ID + ") " +
")";
public static final String SQL_CREATE_EVENT =
"CREATE TABLE " + EventEntry.TABLE_NAME + " (" +
EventEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
EventEntry.COLUMN_NAME_ALBUM_ID + " INTEGER, " +
EventEntry.COLUMN_NAME_TITLE + " TEXT, " +
EventEntry.COLUMN_NAME_SUBTITLE + " TEXT, " +
"FOREIGN KEY (" + EventEntry.COLUMN_NAME_ALBUM_ID + ") " +
"REFERENCES " + AlbumEntry.TABLE_NAME + "(" + AlbumEntry._ID + ") " +
")";
public static final String SQL_CREATE_ALBUM =
"CREATE TABLE " + AlbumEntry.TABLE_NAME + " (" +
AlbumEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
AlbumEntry.COLUMN_NAME_TITLE + " TEXT, " +
AlbumEntry.COLUMN_NAME_SUBTITLE + " TEXT)";
}
该应用程序允许用户将 captions/descriptions 存储到设备上的图像中,因此如果用户对图像进行注释,则图像 ID + 标题将存储在 photo
table .与 stack
table 存在 1:n 关系,其中多个图像可以是 "stack" 的一部分。此外,照片序列(严格假设 increasing/consecutive ID)可以分组为 event
。并且可以将多个事件分组为 album
。我正在尝试使用外键约束将其形式化。
但我想从小处着手,仅使用 photo
table 并让它发挥作用 :) 我的问题是:如何通过迁移在正确的方向下车,如onUpgrade()
等等?我想第一次迁移是从没有数据库到设置数据库?
public class MyappDbHelper extends SQLiteOpenHelper {
// If you change the database schema, you must increment the database version.
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "Myapp.db";
public MyappDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
//db.execSQL(AlbumContract.SQL_CREATE_ALBUM); // I'm starting with just the PHOTO and STACK tables
//db.execSQL(AlbumContract.SQL_CREATE_EVENT);
db.execSQL(AlbumContract.SQL_CREATE_PHOTO);
db.execSQL(AlbumContract.SQL_CREATE_STACK);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//db.execSQL(SQL_DELETE_ENTRIES);
onCreate(db);
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
}
看来您正在尝试使用旧方法来创建 SQLite 数据库。如果您使用 Room 库来处理 SQLite,那么您必须为您的数据创建 @Entity
和 @Dao
(数据访问对象)classes,并且 @Database
class 扩展 RoomDatabase
.
您的案例代码如下所示:
@Entity
public class Photo {
@PrimaryKey
public int photoId;
@ColumnInfo(name = "mediastoreUri")
public String mediastoreUri;
@ColumnInfo(name = "description")
public String description;
@ColumnInfo(name = "photoEventId")
public long photoEventId;
}
@Entity
public class Event {
@PrimaryKey
public int eventId;
@ColumnInfo(name = "title")
public String title;
@ColumnInfo(name = "subtitle")
public String subtitle;
}
// One-to-Many relationship
public class EventWithPhotos {
@Embedded
public Event event;
@Relation(
parentColumn = "eventId",
entityColumn = "photoEventId"
)
public List<Photo> photos;
}
@Dao
public interface PhotoDao {
@Query("SELECT * FROM Photo")
List<Photo> getAll();
@Query("SELECT * FROM Photo WHERE photoId IN (:ids)")
List<Photo> loadAllByIds(int[] ids);
@Insert
void insertAll(Photo... photos);
@Delete
void delete(Photo photo);
}
@Database(entities = {Photo.class, Event.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract PhotoDao userDao();
}
有关详细信息,请参阅:Room overview, Relationships in Room, Migrations in Room
我正致力于在我的应用程序中设置一个小型 SQLite 数据库,该数据库到目前为止一直将数据存储在 OS MediaStore 中。我想远离它,并使用 Room。
最初的table非常简单,基本上只是一个用于描述的TEXT字段,以及MediaStore中实际图像的一些ID。但是,我也想设置其他几个 table。这看起来有点合理吗:
import android.provider.BaseColumns;
import android.provider.MediaStore;
public class AlbumContract {
public static class PhotoEntry implements BaseColumns {
public static final String TABLE_NAME = "photo";
public static final String COLUMN_NAME_IMAGE_ID = "fk_image_id";
public static final String COLUMN_NAME_IMAGE_URI = "mediastore_uri";
public static final String COLUMN_NAME_EVENT_ID = "fk_event_id";
public static final String COLUMN_NAME_STACK_ID = "fk_stack_id";
public static final String COLUMN_NAME_DESCRIPTION = "description";
}
public static class StackEntry implements BaseColumns {
public static final String TABLE_NAME = "stack";
public static final String COLUMN_NAME_STACK_LEADER = "fk_photo_id";
}
public static class EventEntry implements BaseColumns {
public static final String TABLE_NAME = "event";
public static final String COLUMN_NAME_TITLE = "title";
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
public static final String COLUMN_NAME_ALBUM_ID = "fk_album_id";
}
public static class AlbumEntry implements BaseColumns {
public static final String TABLE_NAME = "album";
public static final String COLUMN_NAME_TITLE = "title";
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
}
public static final String SQL_CREATE_PHOTO =
"CREATE TABLE " + PhotoEntry.TABLE_NAME + " (" +
PhotoEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
PhotoEntry.COLUMN_NAME_IMAGE_ID + " INTEGER, " +
PhotoEntry.COLUMN_NAME_IMAGE_URI + " TEXT, " +
PhotoEntry.COLUMN_NAME_STACK_ID + " INTEGER, " +
PhotoEntry.COLUMN_NAME_EVENT_ID + " INTEGER, " +
PhotoEntry.COLUMN_NAME_DESCRIPTION + " TEXT, " +
// Foreign key to MediaStore.Images
"FOREIGN KEY (" + PhotoEntry.COLUMN_NAME_IMAGE_ID + ") " +
"REFERENCES " + MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "(" + MediaStore.Images.Media._ID + ") " +
// Foreign key to "stack" table
"FOREIGN KEY (" + PhotoEntry.COLUMN_NAME_STACK_ID + ") " +
"REFERENCES " + StackEntry.TABLE_NAME + "(" + StackEntry._ID + ") " +
// Foreign key to "event" table
"FOREIGN KEY (" + PhotoEntry.COLUMN_NAME_EVENT_ID + ") " +
"REFERENCES " + EventEntry.TABLE_NAME + "(" + EventEntry._ID + ") " +
")";
public static final String SQL_CREATE_STACK =
"CREATE TABLE " + StackEntry.TABLE_NAME + " (" +
StackEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
StackEntry.COLUMN_NAME_STACK_LEADER + " INTEGER " +
"FOREIGN KEY (" + StackEntry.COLUMN_NAME_STACK_LEADER + ") " +
"REFERENCES " + PhotoEntry.TABLE_NAME + "(" + PhotoEntry._ID + ") " +
")";
public static final String SQL_CREATE_EVENT =
"CREATE TABLE " + EventEntry.TABLE_NAME + " (" +
EventEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
EventEntry.COLUMN_NAME_ALBUM_ID + " INTEGER, " +
EventEntry.COLUMN_NAME_TITLE + " TEXT, " +
EventEntry.COLUMN_NAME_SUBTITLE + " TEXT, " +
"FOREIGN KEY (" + EventEntry.COLUMN_NAME_ALBUM_ID + ") " +
"REFERENCES " + AlbumEntry.TABLE_NAME + "(" + AlbumEntry._ID + ") " +
")";
public static final String SQL_CREATE_ALBUM =
"CREATE TABLE " + AlbumEntry.TABLE_NAME + " (" +
AlbumEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
AlbumEntry.COLUMN_NAME_TITLE + " TEXT, " +
AlbumEntry.COLUMN_NAME_SUBTITLE + " TEXT)";
}
该应用程序允许用户将 captions/descriptions 存储到设备上的图像中,因此如果用户对图像进行注释,则图像 ID + 标题将存储在 photo
table .与 stack
table 存在 1:n 关系,其中多个图像可以是 "stack" 的一部分。此外,照片序列(严格假设 increasing/consecutive ID)可以分组为 event
。并且可以将多个事件分组为 album
。我正在尝试使用外键约束将其形式化。
但我想从小处着手,仅使用 photo
table 并让它发挥作用 :) 我的问题是:如何通过迁移在正确的方向下车,如onUpgrade()
等等?我想第一次迁移是从没有数据库到设置数据库?
public class MyappDbHelper extends SQLiteOpenHelper {
// If you change the database schema, you must increment the database version.
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "Myapp.db";
public MyappDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
//db.execSQL(AlbumContract.SQL_CREATE_ALBUM); // I'm starting with just the PHOTO and STACK tables
//db.execSQL(AlbumContract.SQL_CREATE_EVENT);
db.execSQL(AlbumContract.SQL_CREATE_PHOTO);
db.execSQL(AlbumContract.SQL_CREATE_STACK);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//db.execSQL(SQL_DELETE_ENTRIES);
onCreate(db);
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
}
看来您正在尝试使用旧方法来创建 SQLite 数据库。如果您使用 Room 库来处理 SQLite,那么您必须为您的数据创建 @Entity
和 @Dao
(数据访问对象)classes,并且 @Database
class 扩展 RoomDatabase
.
您的案例代码如下所示:
@Entity
public class Photo {
@PrimaryKey
public int photoId;
@ColumnInfo(name = "mediastoreUri")
public String mediastoreUri;
@ColumnInfo(name = "description")
public String description;
@ColumnInfo(name = "photoEventId")
public long photoEventId;
}
@Entity
public class Event {
@PrimaryKey
public int eventId;
@ColumnInfo(name = "title")
public String title;
@ColumnInfo(name = "subtitle")
public String subtitle;
}
// One-to-Many relationship
public class EventWithPhotos {
@Embedded
public Event event;
@Relation(
parentColumn = "eventId",
entityColumn = "photoEventId"
)
public List<Photo> photos;
}
@Dao
public interface PhotoDao {
@Query("SELECT * FROM Photo")
List<Photo> getAll();
@Query("SELECT * FROM Photo WHERE photoId IN (:ids)")
List<Photo> loadAllByIds(int[] ids);
@Insert
void insertAll(Photo... photos);
@Delete
void delete(Photo photo);
}
@Database(entities = {Photo.class, Event.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract PhotoDao userDao();
}
有关详细信息,请参阅:Room overview, Relationships in Room, Migrations in Room