Комната Android - ошибка ограничения внешнего ключа (код 787) - PullRequest
0 голосов
/ 04 ноября 2019

Я новичок в разработке для Android и пытаюсь создать поездку, в которой много локаций. Создается поездка, затем осуществляется доступ и создается местоположение с использованием trip_id, переданного из предыдущего действия. Я использую LiveData для хранения Списка данных и отображения их в RecyclerView.

Я пробовал многие из опубликованных здесь решений, таких как использование UUID для первичных ключей вместо их автоматической генерации: Ограничение FOREIGN KEY для Android Room не выполнено .

Тем не менее, я все еще получаю ту же ошибку. Так что это оригинальный код, без UUID.

Trip.java

@Entity(tableName = "trip_table",
        indices = {@Index(value = {"location_Id"}, unique = true),
                @Index(value = {"tripNo"}, unique = true)})

public class Trip {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo (name = "location_Id")
    private int id;

    private String title;

    private String description;

    private int priority;

    private int tripNo;

    public Trip(String title, String description, int priority) {
        this.title = title;
        this.description = description;
        this.priority = priority;
    }
// getter, setters

Location.java

@Entity(tableName = "location_table",
        foreignKeys = @ForeignKey(entity = Trip.class, parentColumns = "tripNo", childColumns = "trip_Id"),
        indices = {@Index(value = {"trip_Id"})})

public class Location {

    @PrimaryKey(autoGenerate = true)
    private int locationId;

    @ColumnInfo (name = "trip_Id")
    private int tripId;

    private String locationName;

    @TypeConverters(LatLngConverter.class)
    private LatLng latLng;

    public Location(int tripId, String locationName, LatLng latLng) {
        this.tripId = tripId;
        this.locationName = locationName;
        this.latLng = latLng;
    }
// getter, setters

Создание нового Trip в MainActivity.java.

Trip trip = new Trip(title, description, priority);
tripViewModel.insert(trip);
tripViewModel.updateTripNo();

Передача trip_id к следующему занятию

public void onTripItemClick(Trip trip) {
Intent intent = new Intent(MainActivity.this, viewTripLocations.class);
intent.putExtra(viewTripLocations.EXTRA_TRIP_ID, trip.getId());
Log.d("TRIPINFO", "Trip ID is " + trip.getId()); // D/TRIPINFO: Trip ID is 2
Log.d("TRIPINFO", "Trip No is " + trip.getTripNo()); // D/TRIPINFO: Trip No is 2
startActivity(intent);
}

Это прекрасно работает и отображается в RecyclerView, что позволяет мне щелкнуть по нему, чтобы перейти к следующему занятию: viewTripLocations. java.

После ввода имени и координат LatLng в другом действии метод onActivityResult запускается и возвращается к viewTripLocations.java.

protected void onActivityResult(int requestCode, int resultCode, Intent data)
// codes getting name, latlng

Intent intent = getIntent();
Bundle bundle = intent.getExtras();
int tripId = ((int)(bundle.get(EXTRA_TRIP_ID)));
Location location = new Location(tripId, locationName, locationLatLng);

Log.d("Trip ID is ", "" +tripId); //D/Trip ID used is: 2
Log.d("LOCINFO","Location is " + location.getLocationName() + " ID is " + location.getLocationId() + " REFERENCES Trip " + location.getTripId()); // D/LOCINFO: Location is v ID is 0 REFERENCES Trip 2

locationViewModel.insert(location); //crashes here

Это ошибка, выведенная

D/Trip ID is : 1
D/TRIPINFO: Trip is 23/11/2019 ID is 1
D/LOCINFO: Location is Tokyo ID is 0 REFERENCES Trip 1
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #3
    Process: com.example.TravelPlanner, PID: 9117
    java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:354)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY[787])
        at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:995)
        at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
        at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
        at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:51)
        at androidx.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:64)
        at com.example.travelplanner.LocationDao_Impl.insert(LocationDao_Impl.java:110)
        at com.example.travelplanner.LocationRepository$InsertLocationAsyncTask.doInBackground(LocationRepository.java:51)
        at com.example.travelplanner.LocationRepository$InsertLocationAsyncTask.doInBackground(LocationRepository.java:42)
        at android.os.AsyncTask$2.call(AsyncTask.java:333)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:764) 

Чтобы добавить, использование DB Browser позволило мне подтвердить вставку Trip с помощью tripViewModel.insert (trip).

Я понимаю, почему происходит ошибка, но не понимаю, как создается объект Trip. заранее

Поскольку я все еще неопытен, я мог бы делать некоторые вещи неправильно, поэтому я был бы признателен за помощь.

1 Ответ

0 голосов
/ 05 ноября 2019

Когда вы вставляете объект местоположения в базу данных, связанный с ним внешний ключ недоступен в родительской таблице, т.е. в вашей таблице Trip. Вам нужно отладить эту строку и ее предыдущие вызовы

int tripId = ((int)(bundle.get(EXTRA_TRIP_ID))); // Whether the ID return by this line is exist in the database or not, it it does then pass it into the location constructor.
...