Java 房间数据库-外键约束失败错误代码787
我遇到了上面的问题,即使看到其他类似的问题及其解决方案,以及关于外键的sqlite文档,我也无法解决 我知道在子表中创建外键之前,必须先在父表中存在外键。然而,即使这是第一次这样做,问题仍然存在 这就是我的程序在崩溃之前的运行方式: MainActivity->Create Trip->显示为RecyclerView->单击它输入另一个活动(传递其Trip\u id)->创建位置->选择保存时崩溃(Trip\u id、locationName、latLng) 在这种情况下,Trip有一个PK:Trip_id,而Location将其作为FKJava 房间数据库-外键约束失败错误代码787,java,android,android-sqlite,android-room,Java,Android,Android Sqlite,Android Room,我遇到了上面的问题,即使看到其他类似的问题及其解决方案,以及关于外键的sqlite文档,我也无法解决 我知道在子表中创建外键之前,必须先在父表中存在外键。然而,即使这是第一次这样做,问题仍然存在 这就是我的程序在崩溃之前的运行方式: MainActivity->Create Trip->显示为RecyclerView->单击它输入另一个活动(传递其Trip\u id)->创建位置->选择保存时崩溃(Trip\u id、locationName、latLng) 在这种情况下,Trip有一个PK:T
Process: com.example.TravelPlanner, PID: 4701
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:48)
at com.example.travelplanner.LocationRepository$InsertLocationAsyncTask.doInBackground(LocationRepository.java:39)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
这是在onActivityResult方法的第二个活动中创建Location对象的行
String locationName = data.getStringExtra("locationName");
String latLng = data.getStringExtra("latLng");
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
int tripId = (int)bundle.get("tripId"); // D/TRIPID: Trip id is 1
Log.d("TRIPID", "Trip id is " + tripId);
String[] latlong = latLng.split(",");
double latitude = Double.parseDouble(latlong[0]);
double longitude = Double.parseDouble(latlong[1]);
LatLng locationLatLng = new LatLng(latitude,longitude);
Location location = new Location(tripId, locationName, locationLatLng);
Log.d("LOCATIONID", "Trip id is " + location.getTripId()); // D/LOCATIONID: Trip id is 1
locationViewModel.insert(location); //crashes here
Location.class
@Entity(tableName = "location_table",foreignKeys = @ForeignKey(entity = Trip.class, parentColumns = "location_Id", 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;
}
旅行班
@Entity(tableName = "trip_table",
indices = {@Index(value = {"location_Id"},
unique = true)})
public class Trip {
@PrimaryKey(autoGenerate = true)
@ColumnInfo (name = "location_Id")
private int id;
private String title;
private String description;
private int priority;
//id will be auto generated so it need not be inside constructor
public Trip(String title, String description, int priority) {
this.title = title;
this.description = description;
this.priority = priority;
}
我看不出这是如何在将外键添加到父表中之前添加外键的…显示的代码似乎没有任何问题,即使用您的代码(为了方便起见,稍微修改了一下(只需在主线程上运行long for latLng) 然后使用:-
appDatabase = Room.databaseBuilder(this,AppDatabase.class,"travel_planner")
.allowMainThreadQueries()
.build();
Trip trip1 = new Trip("A Trip","My first trip",1);
int tripID = (int) appDatabase.tripDao().insertTrip(trip1);
appDatabase.locationDao().insertLocation(new Location(tripID,"Here",100));
appDatabase.locationDao().insertLocation(new Location(tripID,"Here again",200));
List<Trip> tripList = appDatabase.tripDao().getAllTrips();
for (Trip t: tripList) {
Log.d("TRIPINFO","Trip is " + t.getDescription() + " ID is " + t.getId());
}
List<Location> locationList = appDatabase.locationDao().getAllLocations();
for (Location l: locationList) {
Log.d("LOCINFO","Location is " + l.getLocationName() + " ID is " + l.getLocationId() + " REFERENCES Trip " + l.getTripId());
}
i、 e TripId1存在,并添加了两个位置,参考该行程
同样地
抽象TripDao TripDao();
在@Database类中编码(AppDatabase
在下面使用))这将列出当前跳闸和要添加的位置。假设出现故障,则跳闸id和参考跳闸值之间存在差异。如果跳闸不存在,则由于某种原因,不会添加跳闸,否则将传递不正确的TripId。以上内容应有助于确定是哪种情况 感谢您再次关注我的问题。我尝试了您的方法,但我使用的是LiveData,因此我无法使用foreach获取tripId。但是,我尝试了使用Log.d(“tripId”,“Trip id为”+tripId);在onActivityResult类中创建tripId变量后,得到了1。之后,我使用了Log.d(“LOCATIONID”,“Trip id为”+location.getTripId());将tripId添加到location对象后,它也显示为1。D/tripId:Trip id为1 D/LOCATIONID:Trip id为1也要注意,在start@Ferain尽管您不相信,但这表明id为1的跳闸行不存在。这就是为什么检查跳闸行是否为ta很重要的原因ble确实有这样一行。据猜测,您的问题很可能是如何从recycler视图中获取trip id。您已经尝试了您建议的方法,即使在插入新的trip数据后立即检查,for循环也不会输出任何内容。但是,我使用了SQL ite的DB Browser,它显示数据在数据库中。因此我现在真的很困惑
2019-10-31 06:28:09.591 27335-27335/? D/TRIPINFO: Trip is My first trip ID is 1
2019- 10-31 06:28:09.593 27335-27335/? D/LOCINFO: Location is Here ID is 1 REFERENCES Trip 1
2019-10-31 06:28:09.593 27335-27335/? D/LOCINFO: Location is Here again ID is 2 REFERENCES Trip 1
@Query("SELECT * FROM trip_table")
List<Trip> getAllTrips();
List<Trip> tripList = appDatabase.tripDao().getAllTrips();
for (Trip t: tripList) {
Log.d("TRIPINFO","Trip is " + t.getDescription() + " ID is " + t.getId());
}
Log.d("LOCINFO","Location is " + location.getLocationName() + " ID is " + location.getLocationId() + " REFERENCES Trip " + location.getTripId());