В настоящее время я создаю приложение управления запасами для деятельности в точках продаж. Здесь я должен включить функцию базы данных с 3 таблицами: пункт , счет и корзина . В соответствии с официальной документацией Android (https://developer.android.com/training/data-storage/sqlite), настоятельно рекомендуется использовать библиотеку Room из-за недостатка без него: без проверки во время компиляции, большого количества стандартного кода. После этого я решил попробовать .
Во-первых, я начал тестировать реализацию Room, используя одну таблицу. Чтобы определить item , я создал 3 объекта: Item class, ItemDao interface и POSDatabase class. В результате все запросы выполняются успешно.
Однако, когда я попытался ввести другую сущность, invoice , он выдает ошибку в Run build и Java-компиляторе во время Make. Я попытался решить проблему путем переноса базы данных в соответствии с рекомендациями Суслова (https://medium.com/@kirillsuslov/how-to-add-more-that-one-entity-in-room-5cc3743219c0). Несмотря на редактирование, возникают похожие ошибки.
Наконец, я хотел бы знать, как правильно определить более одной таблицы, используя Room. Но, кроме этого, мне также нужно некоторое понимание ошибок. Спасибо за внимание.
Попытка обхода
Согласно Суслову, для введения дополнительных таблиц в базу данных требуется миграция. В источнике также упоминается, что определение миграции следует поместить в наследник RoomDatabase ( POSDatabase ).
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS `invoice` (`invoice_id` VARCHAR, "
+ "`terminal_no` VARCHAR NOT NULL, `cashier_name` TEXT, PRIMARY KEY(`invoice_id`))");
}
};
MIGRATION_1_2 затем включается во время вызова:
Room.databaseBuilder(context.getApplicationContext(),
POSDatabase.class,
"pos_database").addMigrations(MIGRATION_1_2).build();
Item.java
package com.example.qrreceipt;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity(tableName = "item")
public class Item {
@PrimaryKey
@NonNull
@ColumnInfo(name = "item_id")
private String item_id;
@ColumnInfo(name = "description")
private String description;
@ColumnInfo(name = "price")
private double price;
public Item() { }
@NonNull
public String getItem_id() {
return item_id;
}
public String getDescription() {
return description;
}
public double getPrice() {
return price;
}
public void setItem_id(@NonNull String item_id) {
this.item_id = item_id;
}
public void setDescription(String description) {
this.description = description;
}
public void setPrice(double price) {
this.price = price;
}
}
* * ItemDao.java тысяча сорок-девять
package com.example.qrreceipt;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
@Dao
public interface ItemDao {
@Insert
void insertItem(Item item);
@Update
void updateItem(Item item);
@Query("SELECT * FROM item WHERE item_id = :item_id")
List<Item> findItem(String item_id);
@Query("SELECT * FROM item")
List<Item> getAllItems();
@Query("DELETE FROM item WHERE item_id = :item_id")
void deleteItem(String item_id);
}
POSDatabase.java
package com.example.qrreceipt;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
@Database(entities = {Item.class, Invoice.class}, version = 2, exportSchema = false)
public abstract class POSDatabase extends RoomDatabase {
public abstract ItemDao getItemDAO();
public abstract InvoiceDao getInvoiceDAO();
private static POSDatabase INSTANCE;
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS `invoice` (`invoice_id` VARCHAR, "
+ "`terminal_no` VARCHAR NOT NULL, `cashier_name` TEXT, PRIMARY KEY(`invoice_id`))");
}
};
static POSDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (POSDatabase.class) {
if (INSTANCE == null) {
INSTANCE =
Room.databaseBuilder(context.getApplicationContext(),
POSDatabase.class,
"pos_database").addMigrations(MIGRATION_1_2).build();
}
}
}
return INSTANCE;
}
}
Invoice.java
package com.example.qrreceipt;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity(tableName = "invoice")
public class Invoice {
@PrimaryKey
@NonNull
@ColumnInfo(name = "invoice_id")
private String invoice_id;
//private Date date;
@ColumnInfo(name = "terminal_no")
private String terminal_no;
@ColumnInfo(name = "cashier_name")
private String cashier_name;
public Invoice() { }
@NonNull
public String getInvoice_id() {
return invoice_id;
}
public String getTerminal_no() {
return terminal_no;
}
public String getCashier_name() {
return cashier_name;
}
public void setInvoice_id(@NonNull String invoice_id) {
this.invoice_id = invoice_id;
}
public void setTerminal_no(String terminal_no) {
this.terminal_no = terminal_no;
}
public void setCashier_name(String cashier_name) {
this.cashier_name = cashier_name;
}
}
InvoiceDao.java
package com.example.qrreceipt;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
@Dao
public interface InvoiceDao {
@Insert
void insertInvoice(Invoice invoice);
@Update
void updateInvoice(Invoice invoice);
@Query("SELECT * FROM invoice WHERE invoice_id = :invoice_id")
List<Item> findInvoice(String invoice_id);
@Query("SELECT * FROM invoice")
List<Item> getAllInvoices();
@Query("DELETE FROM invoice WHERE invoice_id = :invoice_id")
void deleteInvoice(String invoice_id);
}
Выполнить сборку> Выполнить задачи>: app: compileDebugJavaWithJavac
org.gradle.api.tasks.TaskExecutionException: выполнение задачи не выполнено
': Приложение: compileDebugJavaWithJavac. в
org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute (ExecuteActionsTaskExecuter.java:95)
в
org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute (ResolveTaskOutputCachingStateExecuter.java:91)
в
org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute (ValidatingTaskExecuter.java:57)
в
org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute (SkipEmptySourceFilesTaskExecuter.java:119)
в
org.gradle.api.internal.tasks.execution.ResolvePreviousStateExecuter.execute (ResolvePreviousStateExecuter.java:43)
в
org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute (CleanupStaleOutputsExecuter.java:93)
в
org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute (FinalizePropertiesTaskExecuter.java:45)
в
org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute (ResolveTaskArtifactStateTaskExecuter.java:94)
в
org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute (SkipTaskWithNoActionsExecuter.java:56)
в
org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute (SkipOnlyIfTaskExecuter.java:55)
в
org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute (CatchExceptionTaskExecuter.java:36)
в
org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter $ 1.executeTask (EventFiringTaskExecuter.java:67)
в
org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter $ 1.call (EventFiringTaskExecuter.java:52)
в
org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter $ 1.call (EventFiringTaskExecuter.java:49)
в
org.gradle.internal.operations.DefaultBuildOperationExecutor $ CallableBuildOperationWorker.execute (DefaultBuildOperationExecutor.java:315)
вorg.gradle.internal.operations.DefaultBuildOperationExecutor $ CallableBuildOperationWorker.execute (DefaultBuildOperationExecutor.java:305)
в
org.gradle.internal.operations.DefaultBuildOperationExecutor.execute (DefaultBuildOperationExecutor.java:175)
в
org.gradle.internal.operations.DefaultBuildOperationExecutor.call (DefaultBuildOperationExecutor.java:101)
в
org.gradle.internal.operations.DelegatingBuildOperationExecutor.call (DelegatingBuildOperationExecutor.java:36)
в
org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute (EventFiringTaskExecuter.java:49)
в
org.gradle.execution.plan.LocalTaskNodeExecutor.execute (LocalTaskNodeExecutor.java:43)
в
org.gradle.execution.taskgraph.DefaultTaskExecutionGraph $ InvokeNodeExecutorsAction.execute (DefaultTaskExecutionGraph.java:355)
в
org.gradle.execution.taskgraph.DefaultTaskExecutionGraph $ InvokeNodeExecutorsAction.execute (DefaultTaskExecutionGraph.java:343)
в
org.gradle.execution.taskgraph.DefaultTaskExecutionGraph $ BuildOperationAwareExecutionAction.execute (DefaultTaskExecutionGraph.java:336)
в
org.gradle.execution.taskgraph.DefaultTaskExecutionGraph $ BuildOperationAwareExecutionAction.execute (DefaultTaskExecutionGraph.java:322)
в
org.gradle.execution.plan.DefaultPlanExecutor $ ExecutorWorker $ 1.execute (DefaultPlanExecutor.java:134)
в
org.gradle.execution.plan.DefaultPlanExecutor $ ExecutorWorker $ 1.execute (DefaultPlanExecutor.java:129)
в
org.gradle.execution.plan.DefaultPlanExecutor $ ExecutorWorker.execute (DefaultPlanExecutor.java:202)
в
org.gradle.execution.plan.DefaultPlanExecutor $ ExecutorWorker.executeNextNode (DefaultPlanExecutor.java:193)
в
org.gradle.execution.plan.DefaultPlanExecutor $ ExecutorWorker.run (DefaultPlanExecutor.java:129)
в
org.gradle.internal.concurrent.ExecutorPolicy $ CatchAndRecordFailures.onExecute (ExecutorPolicy.java:63)
в
org.gradle.internal.concurrent.ManagedExecutorImpl $ 1.run (ManagedExecutorImpl.java:46)
в
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1142)
в
java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:617)
в
org.gradle.internal.concurrent.ThreadFactoryImpl $ ManagedThreadRunnable.run (ThreadFactoryImpl.java:55)
at java.lang.Thread.run (Thread.java:745) Причина:
org.gradle.api.internal.tasks.compile.CompilationFailedException:
Компиляция не удалась; см. вывод ошибки компилятора для деталей. в
org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute (JdkJavaCompiler.java:52)
в
org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute (JdkJavaCompiler.java:36)
в
org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors (NormalizingJavaCompiler.java:100)
в
org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute (NormalizingJavaCompiler.java:52)
в
org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute (NormalizingJavaCompiler.java:38)
в
org.gradle.api.internal.tasks.compile.AnnotationProcessorDiscoveringCompiler.execute (AnnotationProcessorDiscoveringCompiler.java:51)
в
org.gradle.api.internal.tasks.compile.AnnotationProcessorDiscoveringCompiler.execute (AnnotationProcessorDiscoveringCompiler.java:37)
в
org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute (CleaningJavaCompilerSupport.java:39)
в
org.gradle.api.internal.tasks.compile.incremental.IncrementalCompilerFactory $ 2.execute (IncrementalCompilerFactory.java:110)
в
org.gradle.api.internal.tasks.compile.incremental.IncrementalCompilerFactory $ 2.execute (IncrementalCompilerFactory.java:106)
в
org.gradle.api.internal.tasks.compile.incremental.IncrementalResultStoringCompiler.execute (IncrementalResultStoringCompiler.java:59)
в
org.gradle.api.internal.tasks.compile.incremental.IncrementalResultStoringCompiler.execute (IncrementalResultStoringCompiler.java:43)по адресу org.gradle.api.internal.tasks.compile.CompileJavaBuildOperationReportingCompiler $ 2.call (CompileJavaBuildOperationReportingCompiler.java:59) по адресу org.gradle.api.internal.tasks.compile.CompileJavaBuildOperationReile $ Компиляция репортажа.gradle.internal.сgradle.api.internal.tasks.compile.CompileJavaBuildOperationReportingCompiler.execute (CompileJavaBuildOperationReportingCompiler.java:51) в org.gradle.api.tasks.compile.JavaCompile.performCompilation (JavaCompile.java:154) в org.gradle.api.tasks.compile.JavaCompile.compile (JavaCompile.java:12).android.build.gradle.tasks.AndroidJavaCompile.compile (AndroidJavaCompile.kt: 214) в sun.reflect.NativeMethodAccessorImpl.invoke0 (нативный метод) в sun.reflect.NativeMethodAccessorImpl.invoke (NativeFmp.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) в java.lang.reflect.Method.invoke (Method.java:498) в org.gradle.internal.reflect.JavaMethod.invoke (JavaMethod).gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute (IncrementalTaskAction.java:47) в org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute (StandardTaskAction.java:dle.ag.g. org. org. org.internal.project.taskfactory.StandardTaskAction.execute (StandardTaskAction.java:28) в org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter $ 2.run (ExecuteActionsTaskExecuter.java:284) в org.gradle..java: 293) в org.gradle.internal.operations.DefaultBuildOperationExecutor.execute (DefaultBuildOperationExecutor.java:175) в org.gradle.internal.operations.DefaultBuildOperationExecutor.run (DefaultBuildOperationExecutor.jternal:gra. orternal.gra.grag или в .in)operations.DelegatingBuildOperationExecutor.run (DelegatingBuildOperationExecutor.java:31) в org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction (ExecuteActionsTaskExecuter.java:273.exas.ecute.executeActions (ExecuteActionsTaskExecuter.java:258) в org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access $ 200 (ExecuteActionsTaskExecuter.java:67) в org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter $ TaskExecution.execute (ExecuteActionsTaskExecuter.java:145) в org.gradle.internal.exte..execute (ExecuteStep.java:49) в org.gradle.internal.execution.impl.steps.CancelExecutionStep.execute (CancelExecutionStep.java:34) в org.gradle.internal.execution.impl.steps.TimeoutStep.executeithoutSout.java: 69) в org.gradle.internal.execution.impl.steps.TimeoutStep.execute (TimeoutStep.java:49) в org.gradle.internal.execution.impl.steps.CatchExceptionStep.execute (CatchExceptionStep.java:33) в org.gradle.internal.execution.impl.steps.CreateOutputsStep.execute (CreateOutputsStep.java:50) вorg.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute (SnapshotOutputStep.java:43) в org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute (SnapshotOutputStep.java:29.)internal.execution.impl.steps.CacheStep.executeWithoutCache (CacheStep.java:134) в org.gradle.internal.execution.impl.steps.CacheStep.lambda $ выполнить $ 3 (CacheStep.java:83) в java.util.Optional.orElseGet (Optional.java:267) в org.gradle.internal.execution.impl.steps.CacheStep.execute (CacheStep.java:82) в org.gradle.internal.execution.impl.steps.CacheStep.execute (CacheStep.java: 36) в org.gradle.internal.execution.impl.steps.PrepareCachingStep.execute (PrepareCachingStep.java:33) в org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute (StoreSnapshotsS38).грadle.internal.execution.impl.steps.SkipUpToDateStep.lambda $ execute $ 0 (SkipUpToDateStep.java:89) в java.util.Optional.map (Optional.java:215) в org.gradle.internal.execution.impl.steps«.java: 34) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute (ExecuteActionsTaskExecuter.java:91) ... еще 35
Компилятор Java: (2 ошибки, 2предупреждения)
Предупреждение. Запрос возвращает несколько столбцов [invoice_id, Terminal_no, cashier_name], которые не используются com.example.qrreceipt.Item.Вы можете использовать аннотацию @ColumnInfo в полях, чтобы указать отображение.com.example.qrreceipt.Item имеет несколько полей [item_id, description, price], которые не возвращаются запросом.Если они не должны быть прочитаны из результата, вы можете пометить их аннотацией @Ignore.Вы можете подавить это предупреждение, аннотируя метод с помощью @SuppressWarnings (RoomWarnings.CURSOR_MISMATCH).Столбцы, возвращаемые запросом: invoice_id, terminal_no, cashier_name.Поля в com.example.qrreceipt.Item: item_id, description, price.
Ошибка: столбцы, возвращаемые запросом, не имеют полей [item_id, price] в com.example.qrreceipt.Item, хотяони аннотируются как ненулевые или примитивные.Столбцы, возвращаемые запросом: [invoice_id, Terminal_no, cashier_name]
Предупреждение. Запрос возвращает некоторые столбцы [invoice_id, Terminal_no, cashier_name], которые не используются com.example.qrreceipt.Item.Вы можете использовать аннотацию @ColumnInfo в полях, чтобы указать отображение.com.example.qrreceipt.Item имеет несколько полей [item_id, description, price], которые не возвращаются запросом.Если они не должны быть прочитаны из результата, вы можете пометить их аннотацией @Ignore.Вы можете подавить это предупреждение, аннотируя метод с помощью @SuppressWarnings (RoomWarnings.CURSOR_MISMATCH).Столбцы, возвращаемые запросом: invoice_id, terminal_no, cashier_name.Поля в com.example.qrreceipt.Item: item_id, описание, цена.
Ошибка: ошибка: столбцы, возвращаемые запросом, не имеют полей [item_id, price] в com.example.qrreceipt.Itemдаже если они аннотированы как ненулевые или примитивные.Столбцы, возвращаемые запросом: [invoice_id, Terminal_no, cashier_name]