我是Android开发的新手,我正在尝试创建一个Trip,其中包含多个位置。使用从上一个活动传递的trip_id,创建一个旅程,然后对其进行访问并创建一个位置。我正在使用LiveData存储数据列表,并将其显示在RecyclerView中。
我已经尝试过这里发布的许多解决方案,例如使用UUID作为主键而不是自动生成它们:Android Room FOREIGN KEY constraint failed。
但是,我仍然遇到相同的错误。这是原始代码,没有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
在MainActivity.java中创建一个新的Trip。
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)
作为补充,使用数据库浏览器允许我使用tripViewModel.insert(trip)确认Trip的插入。
我了解为什么会发生错误,但不了解如何预先创建Trip对象
由于我仍然没有经验,所以我可能做错了一些事情,所以我将不胜感激。
答案 0 :(得分:0)
将位置对象插入数据库时,与其关联的外键在父表(即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.