使用Retrofit2获取数据存入Room数据库时插入User失败求助
Hey there! Let's break down why your User data isn't making it into the Room database—it's a common mapping issue, easy to fix once you spot it.
Root Cause
Looking at your code and the server's JSON response, here's the critical mismatch:
- Your
Userentity uses@SerializedName("_id")for the primary key field_id - But the server returns the user ID under the key
"id"(no leading underscore)
Since Gson can't map "id" from the JSON to your _id field (it's looking for "_id" instead), the _id value in your parsed User objects ends up being null. And because you marked _id with @NonNull as the primary key, Room rejects any insertion where the primary key is null—this is exactly why your inserts are failing.
Fix Steps
1. Correct the Serialization Mapping
Update the @SerializedName annotation on your _id field to match the server's JSON key:
@Entity(tableName = "Users") public class User { @NonNull @PrimaryKey @SerializedName("id") // Changed from "_id" to "id" private String _id; @ColumnInfo(name = "name") @SerializedName("name") @Expose private String name; @ColumnInfo(name = "age") @SerializedName("age") @Expose private String age; // Constructors, getters, setters remain the same }
2. Verify Parsed Objects
Before inserting into Room, add a quick log or debug check to confirm that the _id field of each parsed User is now populated with the correct value from the server:
// After fetching data via Retrofit List<User> users = response.body(); for (User user : users) { Log.d("UserDebug", "User ID: " + user.get_id()); // Should show non-null IDs now }
3. Handle Database Migration (If Needed)
If you've already run the app with the old entity structure, you'll need to update your Room database version to avoid migration errors. In your RoomDatabase subclass:
@Database(entities = {User.class}, version = 2) // Increment version number public abstract class AppDatabase extends RoomDatabase { // DAO definitions }
(For testing, you can use fallbackToDestructiveMigration() during database building, but avoid this in production as it will wipe existing data.)
Optional: Flexible Mapping (For Edge Cases)
If you ever need to support both "id" and "_id" as JSON keys (for backward compatibility), you can use the alternate parameter in @SerializedName:
@SerializedName(value = "id", alternate = "_id") private String _id;
But for your current use case, just changing the value to "id" is the cleanest solution.
内容的提问来源于stack exchange,提问作者Digvijay Singh Thakur

