AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 77164866
Accepted
Matias Chiaia
Matias Chiaia
Asked: 2023-09-24 04:54:04 +0800 CST2023-09-24 04:54:04 +0800 CST 2023-09-24 04:54:04 +0800 CST

O aplicativo falha ao usar o banco de dados de sala pré-preenchido

  • 772

Estou tentando usar um banco de dados Room pré-preenchido, mas recebo uma falha ao tentar usar o banco de dados com o seguinte erro: java.lang.NullPointerException: cursor.getString(toColumnIndex) must not be null

Tudo funciona bem até eu adicionar o createFromAsset("databses/test.db")método, quando ele trava. Nada trava se eu simplesmente não executar o getAllCocktails()método. Já verifiquei se o banco de dados que inseri é igual e não encontrei nenhuma diferença (também verifiquei se os dados são carregados com AppInspection)

Eu não apenas testei, getAllCocktails()também tentei inserir com um construtor totalmente parametrizado

Vou postar (alguns) meus códigos e logs para que seja mais fácil diagnosticar. Tentei com as versões 2.5.1 e 2.5.2 do Room

arquivo teste.db

Atividade:

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();
    }
}

Banco de dados da sala:

@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;
    }
}

GarrafaEntidade:

@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;
    }
}

BottleIngredientEntity:

@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;
    }
}

CoquetelIngredienteEntidade:

@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;
    }
}

EntidadeTipoIngrediente:

@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;
    }
}

Entidade Coquetel:

@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;
    }
}

Coquetel Dao:

@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;
android
  • 1 1 respostas
  • 51 Views

1 respostas

  • Voted
  1. Best Answer
    MikeT
    2023-09-24T05:15:48+08:002023-09-24T05:15:48+08:00

    It all works fine until I add the createFromAsset("databses/test.db") method

    and then from the logcat:-

    cursor.getString(toColumnIndex) must not be null

    Is probably due to the data from the asset having nulls (or at least one null) in a column when the column in the @Entity annotated class does not allow nulls.

    It should also be noted that if you exclude db.cocktailDAO().getAllCocktails(); then the database will not even be accessed and thus not even created. That is just getting an instance of the database does not open the database, the open is delayed until an attempt is made to access the database.

    Summary of findings

    The issue, is as predicted, the asset. However it has nothing to do with the getAllCocktails method other than this is what causes the database to be opened and thus the copy of the asset then the opeing of the database.

    In this case, as the asset is first copied to a temporary database and then to the actual Room database, the exception was (it is believed) the copy from the asset to the actual database where the exception occurred.

    The actual issue being due to discrepancies between the database schema expected (actually required) by Room and the schema of the asset.

    As is always suggested, rather than trying to predict Room VERY STRICT schema requirements, the schema that is available in the generated after successfully compiling the project, should be used.

    See fix below for how this specific issue can be resolved.

    It won't appear to be an issue until you actually try to retrieve the data and hence why the issue only appears when you introduce the data from the asset.

    You have two options:-

    1. modify the @Entity annotated class to allow nulls for the column(s), or
    2. modify the source data to not have nulls.

    You may wish to modify your question to include:-

    1. The @Entity annotated class or classes.
    2. The @Dao annotated class.

    Working example showing the issue is very likely with the asset

    Created AS project using your code (other than using MainActivity instead of PedirTragoActivity) and altered MainActivity to be:-

    public class MainActivity extends AppCompatActivity {
    
        AppDatabase db;
        String TAG = "DBINFO";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            db = AppDatabase.getInstance(this.getApplication());
            logAllCocktails(db.cocktailDAO().getAllCocktails(),"STG01");
            db.cocktailDAO().insertCocktail(new CocktailEntity("C1",false,"Blah1"));
            db.cocktailDAO().insertCocktail(new CocktailEntity("C2",true,"Blah2"));
            db.cocktailDAO().insertCocktail(new CocktailEntity("C3",false,"Blah3"));
            logAllCocktails(db.cocktailDAO().getAllCocktails(),"STG02");
            db.close();
        }
    
        void logAllCocktails(List<CocktailEntity> allCocktails,String tag_suffix) {
            Log.d(TAG +tag_suffix,"Starting Log of All Cocktails where supplied list has " + allCocktails.size() + " items.");
            for (CocktailEntity ce: allCocktails) {
                Log.d(
                        TAG+tag_suffix,
                        "Cocktail Name is " + ce.getName() + " HasIce is " + ce.isHasIce() + " ID is " + ce.getId() + " ImageName is " + ce.getImgName()
                );
            }
        }
    }
    

    Ran the above twice with createFromAsset commented out. Log showed first 0 Cocktails, the after the 3 inserts 3 Cocktails. Second run showed 3 and 6.

    Note the addition of the close (this to force the WAL to be committed so just one file).

    Used Device Explorer to copy the database file into the assets folder and then into the assets/database folder as test.db e.g. :-

    enter image description here

    Uninstalled the App included the createFromAsset code and reran:-

    Resultant Log:-

    2023-09-24 07:51:34.929 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG01: Starting Log of All Cocktails where supplied list has 6 items.
    2023-09-24 07:51:34.929 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG01: Cocktail Name is C1 HasIce is false ID is 1 ImageName is null
    2023-09-24 07:51:34.929 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG01: Cocktail Name is C2 HasIce is true ID is 2 ImageName is null
    2023-09-24 07:51:34.929 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG01: Cocktail Name is C3 HasIce is false ID is 3 ImageName is null
    2023-09-24 07:51:34.929 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG01: Cocktail Name is C1 HasIce is false ID is 4 ImageName is null
    2023-09-24 07:51:34.929 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG01: Cocktail Name is C2 HasIce is true ID is 5 ImageName is null
    2023-09-24 07:51:34.929 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG01: Cocktail Name is C3 HasIce is false ID is 6 ImageName is null
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Starting Log of All Cocktails where supplied list has 9 items.
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Cocktail Name is C1 HasIce is false ID is 1 ImageName is null
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Cocktail Name is C2 HasIce is true ID is 2 ImageName is null
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Cocktail Name is C3 HasIce is false ID is 3 ImageName is null
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Cocktail Name is C1 HasIce is false ID is 4 ImageName is null
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Cocktail Name is C2 HasIce is true ID is 5 ImageName is null
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Cocktail Name is C3 HasIce is false ID is 6 ImageName is null
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Cocktail Name is C1 HasIce is false ID is 7 ImageName is null
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Cocktail Name is C2 HasIce is true ID is 8 ImageName is null
    2023-09-24 07:51:34.953 21370-21370/a.a.so77164866javaroomnpefromasset D/DBINFOSTG02: Cocktail Name is C3 HasIce is false ID is 9 ImageName is null
    
    • i.e. NO NPE Crash
    • Originally the 6 rows from the previous runs, then
    • 9 rows after 3 new rows inserted.
    • Note the constrcutor public CocktailEntity(String name, boolean hasIce, String imaName) was used, hence the nulls for imageName (and that these being null are not an issue)

    Edit using downloaded mediafile test.db

    In short this is fine and works (at both Version 1 and Version 7).

    As such the issue does not appear to be with the supplied code (database wise) nor with the file itself.

    i.e. at Version 7, for a fresh install then the log (as per the code above) results in :-

    2023-09-24 12:01:19.596 D/DBINFOSTG01: Starting Log of All Cocktails where supplied list has 5 items.
    2023-09-24 12:01:19.596 D/DBINFOSTG01: Cocktail Name is campari HasIce is true ID is 1 ImageName is campari
    2023-09-24 12:01:19.596 D/DBINFOSTG01: Cocktail Name is fernet HasIce is true ID is 2 ImageName is fernet
    2023-09-24 12:01:19.596 D/DBINFOSTG01: Cocktail Name is gin tonic HasIce is true ID is 3 ImageName is gintonic
    2023-09-24 12:01:19.596 D/DBINFOSTG01: Cocktail Name is ron cola HasIce is true ID is 4 ImageName is roncola
    2023-09-24 12:01:19.596 D/DBINFOSTG01: Cocktail Name is sex On  the beach HasIce is true ID is 5 ImageName is sexOnTheBeach
    2023-09-24 12:01:19.608 D/DBINFOSTG02: Starting Log of All Cocktails where supplied list has 8 items.
    2023-09-24 12:01:19.608 D/DBINFOSTG02: Cocktail Name is campari HasIce is true ID is 1 ImageName is campari
    2023-09-24 12:01:19.608 D/DBINFOSTG02: Cocktail Name is fernet HasIce is true ID is 2 ImageName is fernet
    2023-09-24 12:01:19.608 D/DBINFOSTG02: Cocktail Name is gin tonic HasIce is true ID is 3 ImageName is gintonic
    2023-09-24 12:01:19.608 D/DBINFOSTG02: Cocktail Name is ron cola HasIce is true ID is 4 ImageName is roncola
    2023-09-24 12:01:19.609 D/DBINFOSTG02: Cocktail Name is sex On  the beach HasIce is true ID is 5 ImageName is sexOnTheBeach
    2023-09-24 12:01:19.609 D/DBINFOSTG02: Cocktail Name is C1 HasIce is false ID is 6 ImageName is null
    2023-09-24 12:01:19.609 D/DBINFOSTG02: Cocktail Name is C2 HasIce is true ID is 7 ImageName is null
    2023-09-24 12:01:19.609 D/DBINFOSTG02: Cocktail Name is C3 HasIce is false ID is 8 ImageName is null
    

    Therefore the issue is perhaps likely to the differences between the two Apps, which could be many.

    • The device (works on AS emulator for 10.1 device API 28)
    • The Activity (very simple initial Activity without anything special layout wise) i.e. the layouts for the Activity are different.
    • You have Entities commented out in the posted code BUT do you have the other entities excluded when testing/running? if not then the log indicates Foreign Key activity. So it may be that the issue is due to NULL being an invalid Foreign Key.
      • error is immediately after at androidx.room.util.TableInfoKt.readForeignKeyFieldMappings(TableInfo.kt:536)
      • kt perhaps indicates Kotlin code, for a java App????

    Edit Adding additional Entities

    • Add BottleEntity, no issues after run.
    • Add BottleIngredientEntity, requires IngredientTypeEntity.
    • Add IngredientTypeEntity NPE cursor.getString(toColumnIndex) must not be null

    So issue is with IngredientTypeEntity/BottleIngredientEnitity

    • commented out FKEY definitions, issue remains.
    • commented out IngredientTYpeEntity, issue remains.
    • commented out BottleIngredientEntity, re-introduced IngredientTypeEntity, no issues after run.

    As such issue very much appears to be with BottleIngredientEntity.

    - note uninstalling App prior to each run.
    

    At this stage comment out createFromAsset to see if issue is with schema rather than data

    • include db.getOpenHelper().getWritableDatabase(); to force open of the database.

    • exclude inserts and logging as probably not an issue.

    • run App, no issue.

    • reintroduce BottleIngredientEntity and run App, not an issue.

    • reintroduce FKEY definitions for BottleIngredientEntity and run App, not an issue.

    So the issue very much appears to be the BottleIngredientEntity and how Room manages handling the asset. iirc that a temp db is used which is then copied.

    • Compare schemas BottleIngredient table:-

    Asset is:-

    CREATE TABLE "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
    )
    

    Room is :-

    CREATE TABLE `bottle_ingredient` (
        `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
        `bottlePos` INTEGER NOT NULL, 
        `ingredientId` INTEGER NOT NULL, 
        FOREIGN KEY(`bottlePos`) REFERENCES `bottles`(`position`) ON UPDATE NO ACTION ON DELETE NO ACTION , 
        FOREIGN KEY(`ingredientId`) REFERENCES `ingredient_types`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION 
    )
    
    • I suspect that even without the NPE issue that an Expected but Found exception would eventuate.

    Advised fix


    My suggestion is to drop using the asset you currently have and use a Tool (know nothing about Datagrip) where YOU create the schema in accordance with Room and populate the data accordingly.

    That is:-

    1. compile the project then inspect the java(generated) (visible from Android Studio's Android View)
    2. locate the AppDatabase_Impl class.
    3. find the createAllTables method in the class and copy the SQL for creating the tables (no need to create room_master_table or insert into it).
    4. change the database version, via the tool or SQL to version 7
    5. populate the tables as required.
    6. save the database ensuring that there is a single file (i.e. no -wal or -shm file) (e.g. with Navicat you have to close navicat for it to fully commit).
    7. then copy this file into the asset.

    note DO NOT turn Foreign Keys off, I suspect that the column cannot be null is due to an invalid reference in the data that you load and that this exception occurs as part of the copying of the asset from the temp to actual db.

    example of getting the CREATE SQL :-

    enter image description here



    FINAL FIX


    As per the above, I believe the core issue is that the SCHEMA of your asset database does not match what Room expects BUT this is masked due to an exception as part of the asset copy when copying the asset to the final Room database from the temporary initial copy.

    So the fix is to use the expected schema, the SQL for which is available in the generate java in the createAllTables method of the AppDatabase_Impl class (i.e. the @Database annotated class suffixed with _Impl).

    To utilise the existing data in the asset, then a conversion can be run. This will rename the existing tables, create the new tables as per the generated SQL and then load the data from the renamed tables. Additionally it will set the user_version (the database version) to 7 (to ensure that fallback doesn't clear the database as there appears to no Migrations, so a version less than 7 would then expect a Migration but in the absence clear the database).

    The SQL script being:-

    SELECT * FROM pragma_user_version;
    /* RUN ALTERS ONCE ONLY ELSE WILL FAIL OR COPY POTENTIALLY NOT ORIGINAL DATA */
    /* COMMENTED OUT AS ALREADY DO ONCE */
    /*
    ALTER TABLE bottles RENAME TO bottles_old;
    ALTER TABLE bottle_ingredient RENAME TO bottle_ingredient_old;
    ALTER TABLE cocktail_ingredients RENAME TO cocktail_ingredients_old;
    ALTER TABLE cocktails RENAME TO cocktails_old;
    ALTER TABLE ingredient_types RENAME TO ingredient_types_old;
    */
     /* Optional DROPS but ensures tables are recreated */
    DROP TABLE IF EXISTS `cocktail_ingredients`; /* best to drop tables with FKEYS first */
    DROP TABLE IF EXISTS `bottle_ingredient`; /* best to drop tables with FKEYS first */
    DROP TABLE IF EXISTS `cocktails`;
    DROP TABLE IF EXISTS `bottles`;
    DROP TABLE IF EXISTS ingredient_types;
    CREATE TABLE IF NOT EXISTS `cocktails` (
        `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
        `name` TEXT, `isOnStock` INTEGER NOT NULL, 
        `hasIce` INTEGER NOT NULL, `imgName` TEXT
    );
    CREATE TABLE IF NOT EXISTS `bottles` (
        `position` INTEGER NOT NULL, `name` TEXT, 
        `capacity` INTEGER NOT NULL, 
        `currentAmount` INTEGER NOT NULL, 
        PRIMARY KEY(`position`)
    );
    /* NOTE MOVED TO BEFORE bottle_ingredients */
    CREATE TABLE IF NOT EXISTS `ingredient_types` (
        `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
        `name` TEXT
    );
    CREATE TABLE IF NOT EXISTS `bottle_ingredient` (
        `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
        `bottlePos` INTEGER NOT NULL, 
        `ingredientId` INTEGER NOT NULL, 
        FOREIGN KEY(`bottlePos`) REFERENCES `bottles`(`position`) ON UPDATE NO ACTION ON DELETE NO ACTION , 
        FOREIGN KEY(`ingredientId`) REFERENCES `ingredient_types`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
    );
    CREATE TABLE IF NOT EXISTS `cocktail_ingredients` (
        `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
        `typeId` INTEGER NOT NULL, 
        `quantity` INTEGER NOT NULL, 
        `cocktailId` INTEGER NOT NULL, 
        FOREIGN KEY(`typeId`) REFERENCES `ingredient_types`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , 
        FOREIGN KEY(`cocktailId`) REFERENCES `cocktails`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION 
    );
    INSERT INTO cocktails SELECT * FROM cocktails_old;
    INSERT INTO bottles SELECT * FROM bottles_old;
    INSERT INTO ingredient_types SELECT * FROM ingredient_types_old;
    INSERT INTO bottle_ingredient SELECT * FROM bottle_ingredient_old;
    INSERT INTO cocktail_ingredients SELECT * FROM cocktail_ingredients_old;
    PRAGMA user_version = 7;
    SELECT * FROM pragma_user_version;
    
    • Note that Navicat was used, Navicat allows multiple statements to be executed and also multiple outputs.
    • Please read comments ESPECIALLY that the ALL important ALTER statements have been commented out.

    Once converted (and checked for the correct/expected data) then save the database file, ensuring that there is no -wal or -shm file (with Navicat you have to close/end Navicat for it to close the file). Then copy the file into the asset and all should be fine.

    • Note you may wish to drop the ????_old tables (but Room will not care that they exist, but they will waste space (minimum 4k per compnent (table index ....))).

    After following the above, uninstalling the App and running then the log (inserts commented out):-

    2023-09-24 14:01:14.970 D/DBINFOSTG02: Starting Log of All Cocktails where supplied list has 5 items.
    2023-09-24 14:01:14.970 D/DBINFOSTG02: Cocktail Name is campari HasIce is true ID is 1 ImageName is campari
    2023-09-24 14:01:14.970 D/DBINFOSTG02: Cocktail Name is fernet HasIce is true ID is 2 ImageName is fernet
    2023-09-24 14:01:14.970 D/DBINFOSTG02: Cocktail Name is gin tonic HasIce is true ID is 3 ImageName is gintonic
    2023-09-24 14:01:14.970 D/DBINFOSTG02: Cocktail Name is ron cola HasIce is true ID is 4 ImageName is roncola
    2023-09-24 14:01:14.970 D/DBINFOSTG02: Cocktail Name is sex On  the beach HasIce is true ID is 5 ImageName is sexOnTheBeach
    

    Using App Inspection (to run a query) shows:-

    enter image description here

    • 0

relate perguntas

  • Rolagem Recyclerview deve cobrir a barra de ferramentas

  • Fundo transbordado por pixels e não funciona função de navegação

  • Escolha uma cor em uma lista, matriz não encontrada no Android

  • Adicionar MapLibre a um novo projeto Android não está funcionando

  • Devo colocar imagens vetoriais em assets ou drawables? Eu tenho mil vetores no meu aplicativo

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve