我正在尝试使用预先填充的 Room 数据库,但在尝试使用该数据库时出现崩溃,并出现以下错误: java.lang.NullPointerException: cursor.getString(toColumnIndex) must not be null
一切正常,直到我添加该createFromAsset("databses/test.db")
方法,当它崩溃时。如果我不执行该getAllCocktails()
方法,则不会发生任何崩溃。我已经检查了我插入的数据库是否完全相同,并且找不到任何差异(我还检查了使用 AppInspection 加载的数据)
我不仅进行了测试,getAllCocktails()
还尝试使用完全参数化的构造函数进行插入
我将发布(一些)我的代码和日志,以便更容易诊断我尝试使用 Room 的版本 2.5.1 和 2.5.2
测试.db文件
活动:
public class PedirTragoActivity extends AppCompatActivity {
AppDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pedir_trago1_1);
db = AppDatabase.getInstance(this.getApplication());
db.cocktailDAO().getAllCocktails();
}
}
房间数据库:
@Database(entities = {
BottleEntity.class,
BottleIngredientEntity.class,
CocktailEntity.class,
CocktailIngredientEntity.class,
IngredientTypeEntity.class
},
version = 7)
public abstract class AppDatabase extends RoomDatabase {
public static AppDatabase INSTANCE;
public abstract BottleDAO bottleDAO();
public abstract BottleIngredientDAO bottleIngredientDAO();
public abstract CocktailDAO cocktailDAO();
public abstract CocktailIngredientDAO cocktailIngredientDAO();
public abstract IngredientTypeDAO ingredientTypeDAO();
public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context, AppDatabase.class, "barbotApp.db")
.allowMainThreadQueries()
.fallbackToDestructiveMigration()
.createFromAsset("databases/test.db")
.build();
}
return INSTANCE;
}
}
瓶子实体:
@Entity(tableName = "bottles")
public class BottleEntity {
@PrimaryKey
@NonNull
private int position;//Del 0 al 7 son alcoholes, el 8 es shaker y del 9 al 16 son mezclas
private String name;
@NonNull
private int capacity;
@NonNull
private int currentAmount;
public BottleEntity() {
}
public BottleEntity(int position, String name, int capacity, int currentAmount) {
this.position = position;
this.name = name;
this.capacity = capacity;
this.currentAmount = currentAmount;
}
@Ignore
public BottleEntity(int position, String name, int capacity) {
this.position = position;
this.name = name;
this.capacity = capacity;
this.currentAmount = capacity;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCapacity() {
return capacity;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
public int getCurrentAmount() {
return currentAmount;
}
public void setCurrentAmount(int currentAmount) {
this.currentAmount = currentAmount;
}
}
瓶子成分实体:
@Entity(tableName = "bottle_ingredient",
foreignKeys = {
@ForeignKey(entity = BottleEntity.class, parentColumns = "position", childColumns = "bottlePos"),
@ForeignKey(entity = IngredientTypeEntity.class, parentColumns = "id", childColumns = "ingredientId")
})
public class BottleIngredientEntity {
@PrimaryKey(autoGenerate = true)
@NonNull
private int id;
@NonNull
private int bottlePos;
@NonNull
private int ingredientId;
public BottleIngredientEntity() {
}
public BottleIngredientEntity(int bottlePos, int ingredientId) {
this.bottlePos = bottlePos;
this.ingredientId = ingredientId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getBottlePos() {
return bottlePos;
}
public void setBottlePos(int bottlePos) {
this.bottlePos = bottlePos;
}
public int getIngredientId() {
return ingredientId;
}
public void setIngredientId(int ingredientId) {
this.ingredientId = ingredientId;
}
}
鸡尾酒成分实体:
@Entity(tableName = "cocktail_ingredients",
foreignKeys = {
@ForeignKey(entity = IngredientTypeEntity.class, parentColumns = "id", childColumns = "typeId"),
@ForeignKey(entity = CocktailEntity.class, parentColumns = "id", childColumns = "cocktailId")
})
public class CocktailIngredientEntity {
@PrimaryKey(autoGenerate = true)
@NonNull
private int id;
@NonNull
private int typeId;
@NonNull
private int quantity;
@NonNull
private int cocktailId;
public CocktailIngredientEntity(int typeId, int quantity, int cocktailId) {
this.typeId = typeId;
this.quantity = quantity;
this.cocktailId = cocktailId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getTypeId() {
return typeId;
}
public void setTypeId(int typeId) {
this.typeId = typeId;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getCocktailId() {
return cocktailId;
}
public void setCocktailId(int cocktailId) {
this.cocktailId = cocktailId;
}
}
成分类型实体:
@Entity(tableName = "ingredient_types")
public class IngredientTypeEntity {
@PrimaryKey(autoGenerate = true)
@NonNull
private int id;
private String name;
public IngredientTypeEntity() {
}
public IngredientTypeEntity(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
鸡尾酒实体:
@Entity(tableName = "cocktails")
public class CocktailEntity {
@PrimaryKey(autoGenerate = true)
@NonNull
private int id;
private String name;
@NonNull
private boolean isOnStock;
@NonNull
private boolean hasIce;
private String imgName;
public CocktailEntity(String name, boolean isOnStock, boolean hasIce, String imgName) {
this.name = name;
this.isOnStock = isOnStock;
this.hasIce = hasIce;
this.imgName = imgName;
}
@Ignore
public CocktailEntity(String name, boolean hasIce, String imaName) {
this.name = name;
this.isOnStock = false;
this.hasIce = hasIce;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isOnStock() {
return isOnStock;
}
public void setOnStock(boolean onStock) {
isOnStock = onStock;
}
public boolean isHasIce() {
return hasIce;
}
public void setHasIce(boolean hasIce) {
this.hasIce = hasIce;
}
public String getImgName() {
return imgName;
}
public void setImgName(String imgName) {
this.imgName = imgName;
}
}
鸡尾酒道:
@Dao
public interface CocktailDAO {
@Insert
long insertCocktail(CocktailEntity cocktail);
@Query("SELECT id FROM cocktails WHERE name = :name")
int getCocktailId(String name);
@Query("SELECT c.* FROM cocktails AS c WHERE c.id = :id")
CocktailEntity getCocktail(int id); //Need to use a repository, separate this 2 parts
@Query("SELECT * FROM cocktails")
List<CocktailEntity> getAllCocktails();
@Query("SELECT cocktails.id FROM cocktails")
List<Integer> getAllCocktailIds();
@Query("SELECT * FROM cocktails" +
" WHERE cocktails.isOnStock = 1")
List<CocktailEntity> getAllCocktailsInStock();
@Query("SELECT isOnStock FROM cocktails WHERE id = :id")
boolean isCocktailInStock(int id);
@Query("UPDATE cocktails SET isOnStock = :isOnStock WHERE id = :id")
void updateCocktailStock(int id, boolean isOnStock);
}
Logcat:
2023-09-23 17:17:20.600 8250-8250 Choreographer com.mecatronica.barbot I Skipped 67 frames! The application may be doing too much work on its main thread.
2023-09-23 17:17:20.801 8250-8594 AdrenoGLES-0 com.mecatronica.barbot I QUALCOMM build : 03e27f8, I326e6aff90
Build Date : 11/02/20
OpenGL ES Shader Compiler Version: EV031.32.02.04
Local Branch : mybrancheb1d781c-1a78-f1f4-8c78-ac1f6bcc2cee
Remote Branch : quic/gfx-adreno.lnx.1.0.r116-rel
Remote Branch : NONE
Reconstruct Branch : NOTHING
2023-09-23 17:17:20.801 8250-8594 AdrenoGLES-0 com.mecatronica.barbot I Build Config : S P 10.0.7 AArch64
2023-09-23 17:17:20.801 8250-8594 AdrenoGLES-0 com.mecatronica.barbot I Driver Path : /vendor/lib64/egl/libGLESv2_adreno.so
2023-09-23 17:17:20.813 8250-8594 AdrenoGLES-0 com.mecatronica.barbot I PFP: 0x016ee190, ME: 0x00000000
2023-09-23 17:17:21.019 8250-8594 LB com.mecatronica.barbot E fail to open file: No such file or directory
2023-09-23 17:17:21.021 8250-8594 OpenGLRenderer com.mecatronica.barbot I Davey! duration=1547ms; Flags=1, IntendedVsync=42335033169415, Vsync=42336149836037, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=42336161943432, AnimationStart=42336162004370, PerformTraversalsStart=42336162065047, DrawStart=42336409293120, SyncQueued=42336445054213, SyncStart=42336445465515, IssueDrawCommandsStart=42336445624838, SwapBuffers=42336577074578, FrameCompleted=42336581385203, DequeueBufferDuration=272760, QueueBufferDuration=682187, GpuCompleted=1893829464,
2023-09-23 17:17:21.027 8250-8250 Looper com.mecatronica.barbot W PerfMonitor doFrame : time=424ms vsyncFrame=0 latency=1127ms procState=2 historyMsgCount=10 (msgIndex=1 wall=1223ms seq=4 running=1128ms runnable=12ms late=2999ms h=android.app.ActivityThread$H w=159) (msgIndex=5 wall=1007ms seq=8 running=2ms runnable=1ms io=4ms late=3591ms h=android.app.ActivityThread$H w=127)
2023-09-23 17:17:21.154 8250-8250 Looper com.mecatronica.barbot W PerfMonitor doFrame : time=35ms vsyncFrame=0 latency=459ms procState=2 historyMsgCount=4 (msgIndex=1 wall=424ms seq=14 running=255ms runnable=1ms late=1127ms h=android.view.Choreographer$FrameHandler c=android.view.Choreographer$FrameDisplayEventReceiver) (msgIndex=4 wall=78ms seq=17 running=70ms runnable=2ms late=413ms h=android.view.ViewRootImpl$ViewRootHandler c=androidx.appcompat.app.AppCompatDelegateImpl$2)
2023-09-23 17:17:28.708 8250-8250 MiuiFrameworkFactory com.mecatronica.barbot V get AllImpl object = android.common.MiuiFrameworkFactoryImpl@b038154
2023-09-23 17:17:28.726 8250-8250 MirrorManager com.mecatronica.barbot W this model don't Support
2023-09-23 17:17:28.773 8250-8250 Timeline com.mecatronica.barbot I Timeline: Activity_launch_request time:42344334
2023-09-23 17:17:28.996 8250-8250 DecorView[] com.mecatronica.barbot D getWindowModeFromSystem windowmode is 1
2023-09-23 17:17:28.997 8250-8250 DecorView com.mecatronica.barbot D createDecorCaptionView windowingMode:1 mWindowMode 1 isFullscreen: true
2023-09-23 17:17:30.631 8250-8250 AndroidRuntime com.mecatronica.barbot D Shutting down VM
2023-09-23 17:17:30.646 8250-8250 AndroidRuntime com.mecatronica.barbot E FATAL EXCEPTION: main
Process: com.mecatronica.barbot, PID: 8250
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mecatronica.barbot/com.mecatronica.barbot.PedirTragoActivity}: java.lang.NullPointerException: cursor.getString(toColumnIndex) must not be null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3550)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3710)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2146)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:8057)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
Caused by: java.lang.NullPointerException: cursor.getString(toColumnIndex) must not be null
at androidx.room.util.TableInfoKt.readForeignKeyFieldMappings(TableInfo.kt:536)
at androidx.room.util.TableInfoKt.readForeignKeys(TableInfo.kt:488)
at androidx.room.util.TableInfoKt.readTableInfo(TableInfo.kt:472)
at androidx.room.util.TableInfo$Companion.read(TableInfo.kt:130)
at androidx.room.util.TableInfo.read(Unknown Source:2)
at com.mecatronica.barbot.database.AppDatabase_Impl$1.onValidateSchema(AppDatabase_Impl.java:136)
at androidx.room.RoomOpenHelper.onCreate(RoomOpenHelper.kt:72)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onCreate(FrameworkSQLiteOpenHelper.kt:244)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:411)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableOrReadableDatabase(FrameworkSQLiteOpenHelper.kt:232)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.innerGetDatabase(FrameworkSQLiteOpenHelper.kt:190)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getSupportDatabase(FrameworkSQLiteOpenHelper.kt:151)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.kt:104)
at androidx.room.SQLiteCopyOpenHelper.getWritableDatabase(SQLiteCopyOpenHelper.kt:71)
at androidx.room.RoomDatabase.inTransaction(RoomDatabase.kt:638)
at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.kt:457)
at com.mecatronica.barbot.database.daos.CocktailDAO_Impl.getAllCocktails(CocktailDAO_Impl.java:177)
at com.mecatronica.barbot.PedirTragoActivity.onCreate(PedirTragoActivity.java:63)
at android.app.Activity.performCreate(Activity.java:8157)
at android.app.Activity.performCreate(Activity.java:8129)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3523)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3710)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2146)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:8057)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
2023-09-23 17:17:30.716 8250-8250 Process com.mecatronica.barbot I Sending signal. PID: 8250 SIG: 9
sql dump form test.db:
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS "ingredient_types"
(
id INTEGER not null
constraint ingredient_types_pk
primary key,
name TEXT
);
INSERT INTO ingredient_types VALUES(1,'SHAKE');
INSERT INTO ingredient_types VALUES(2,'limón');
INSERT INTO ingredient_types VALUES(3,'ron');
INSERT INTO ingredient_types VALUES(4,'tonica');
INSERT INTO ingredient_types VALUES(5,'ginebra');
INSERT INTO ingredient_types VALUES(6,'campari');
INSERT INTO ingredient_types VALUES(7,'naranja');
INSERT INTO ingredient_types VALUES(8,'fernet');
INSERT INTO ingredient_types VALUES(9,'coca');
INSERT INTO ingredient_types VALUES(10,'durazno');
INSERT INTO ingredient_types VALUES(11,'granadina');
INSERT INTO ingredient_types VALUES(12,'vodka');
CREATE TABLE IF NOT EXISTS "bottle_ingredient"
(
id INTEGER not null
constraint bottle_ingredient_pk
primary key,
bottlePos INTEGER not null
constraint bottle_ingredient_bottles_position_fk
references bottles,
ingredientId INTEGER not null
constraint bottle_ingredient_ingredient_types_id_fk
references ingredient_types
);
INSERT INTO bottle_ingredient VALUES(1,8,5);
INSERT INTO bottle_ingredient VALUES(2,9,6);
INSERT INTO bottle_ingredient VALUES(3,10,8);
INSERT INTO bottle_ingredient VALUES(4,11,3);
INSERT INTO bottle_ingredient VALUES(5,12,12);
INSERT INTO bottle_ingredient VALUES(7,0,2);
INSERT INTO bottle_ingredient VALUES(8,1,4);
INSERT INTO bottle_ingredient VALUES(9,2,7);
INSERT INTO bottle_ingredient VALUES(10,3,9);
INSERT INTO bottle_ingredient VALUES(11,4,10);
INSERT INTO bottle_ingredient VALUES(12,5,11);
INSERT INTO bottle_ingredient VALUES(13,16,1);
CREATE TABLE IF NOT EXISTS "bottles"
(
position INTEGER not null
constraint bottles_pk
primary key,
name TEXT,
capacity INTEGER not null,
currentAmount INTEGER not null
);
INSERT INTO bottles VALUES(0,'limon',2000,2000);
INSERT INTO bottles VALUES(1,'tonica',2000,2000);
INSERT INTO bottles VALUES(2,'naranja',2000,2000);
INSERT INTO bottles VALUES(3,'coca',2000,2000);
INSERT INTO bottles VALUES(4,'durazno',2000,2000);
INSERT INTO bottles VALUES(5,'granadina',2000,2000);
INSERT INTO bottles VALUES(6,'Mezcla 7',1,1);
INSERT INTO bottles VALUES(7,'Mezcla 8',1,1);
INSERT INTO bottles VALUES(8,'ginebra',700,700);
INSERT INTO bottles VALUES(9,'campari',750,750);
INSERT INTO bottles VALUES(10,'fernet',750,750);
INSERT INTO bottles VALUES(11,'ron',750,750);
INSERT INTO bottles VALUES(12,'vodka',700,700);
INSERT INTO bottles VALUES(13,'Bottle 6',1,1);
INSERT INTO bottles VALUES(14,'Bottle 7',1,1);
INSERT INTO bottles VALUES(15,'Bottle 8',1,1);
INSERT INTO bottles VALUES(16,'Shakeo',1000,1000);
CREATE TABLE IF NOT EXISTS "cocktail_ingredients"
(
id INTEGER not null
constraint cocktail_ingredients_pk
primary key,
typeId INTEGER not null
constraint cocktail_ingredients_ingredient_types_id_fk
references ingredient_types,
quantity INTEGER not null,
cocktailId INTEGER not null
constraint cocktail_ingredients_cocktails_id_fk
references cocktails
);
INSERT INTO cocktail_ingredients VALUES(1,6,60,1);
INSERT INTO cocktail_ingredients VALUES(2,7,136,1);
INSERT INTO cocktail_ingredients VALUES(3,9,146,2);
INSERT INTO cocktail_ingredients VALUES(4,8,50,2);
INSERT INTO cocktail_ingredients VALUES(5,5,60,3);
INSERT INTO cocktail_ingredients VALUES(6,4,136,3);
INSERT INTO cocktail_ingredients VALUES(7,3,50,4);
INSERT INTO cocktail_ingredients VALUES(8,9,120,4);
INSERT INTO cocktail_ingredients VALUES(9,2,10,4);
INSERT INTO cocktail_ingredients VALUES(10,12,40,5);
INSERT INTO cocktail_ingredients VALUES(11,10,20,5);
INSERT INTO cocktail_ingredients VALUES(12,7,40,5);
INSERT INTO cocktail_ingredients VALUES(13,1,30,5);
INSERT INTO cocktail_ingredients VALUES(14,11,40,5);
CREATE TABLE IF NOT EXISTS "cocktails"
(
id INTEGER not null
constraint cocktails_pk
primary key,
name TEXT,
isOnStock INTEGER not null,
hasIce INTEGER not null,
imgName TEXT
);
INSERT INTO cocktails VALUES(1,'campari',1,1,'campari');
INSERT INTO cocktails VALUES(2,'fernet',1,1,'fernet');
INSERT INTO cocktails VALUES(3,'gin tonic',1,1,'gintonic');
INSERT INTO cocktails VALUES(4,'ron cola',1,1,'roncola');
INSERT INTO cocktails VALUES(5,'sex On the beach',1,1,'sexOnTheBeach');
COMMIT;