简体   繁体   English

Android Room - 外键约束失败(代码 787)错误

[英]Android Room - Foreign Key constraint failed (code 787) error

I am new to Android development and I'm trying to create a Trip which has many Locations in it.我是 Android 开发的新手,我正在尝试创建一个包含许多位置的 Trip。 A trip is created, then accessed and a Location is created by using the trip_id passed from the previous activity.一个行程被创建,然后被访问,并使用从前一个活动传递的trip_id 创建一个位置。 I'm using LiveData to store the List of data and display them in a RecyclerView.我正在使用 LiveData 存储数据列表并将它们显示在 RecyclerView 中。

I have tried many of the solutions posted here, such as using UUID for the primary keys instead of auto-generating them: Android Room FOREIGN KEY constraint failed .我已经尝试了这里发布的许多解决方案,例如使用 UUID 作为主键而不是自动生成它们: Android Room FOREIGN KEY constraint failed

However, I still get the same error.但是,我仍然遇到同样的错误。 So this is the original code, without UUID.所以这是原始代码,没有 UUID。

Trip.java跳闸.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位置.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

Creating a new Trip in MainActivity.java.在 MainActivity.java 中创建一个新的行程。

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

Passing trip_id to the next activity将 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);
}

This works fine and it shows up on the RecyclerView, allowing me to click on it to go into the next activity: viewTripLocations.java.这工作正常,它显示在 RecyclerView 上,允许我单击它到 go 进入下一个活动:viewTripLocations.java。

After entering a name and LatLng coordinates in another activity, the onActivityResult method is triggered and returns to viewTripLocations.java.在另一个activity中输入名称和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

This is the error outputted这是输出的错误

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) 

To add on, using DB Browser allowed me to confirm the insertion of Trip using tripViewModel.insert(trip).另外,使用 DB Browser 让我可以使用 tripViewModel.insert(trip) 确认 Trip 的插入。

I understand why the error happens but do not understand how as a Trip object is created beforehand我明白为什么会发生错误,但不明白如何预先创建 Trip object

As I'm still inexperienced, I might be doing some things wrong so I would appreciate the help.由于我仍然缺乏经验,我可能做错了一些事情,所以我会很感激帮助。

When you're inserting the location object into the database, the foreign key associated with it is not available in the parent table ie your Trip table, You need to debug this line and it's previous calls当您将位置 object 插入数据库时,与其关联的外键在父表(即您的 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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM