Android Room - Get the id of new inserted row with auto-generate
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Room can return the row id of an inserted entity when the primary key is marked as auto-generated. The reliable pattern is to use an auto-generated numeric primary key, return Long from the DAO insert method, and treat 0 as the "not yet assigned" value for new objects.
Define The Entity Correctly
For auto-generated ids, the entity usually looks like this:
With Room's current behavior, if the primary key field is Long or Int, a value of 0 is treated as "not set" during insert when autoGenerate = true.
That is why new entities are usually created with id = 0L.
Return Long From The Insert Method
The DAO method can return the inserted row id directly:
For collections, return a list or array of ids:
This is the cleanest way to get the new id immediately after persistence.
Use The Returned Id In The Repository Layer
Capture the value where the insert happens:
That makes follow-up operations such as navigation, detail loading, or child-record inserts straightforward and safe.
It is much better than inserting first and then querying "the most recent row," which is fragile under concurrency.
Use Transactions For Parent-Child Writes
If you need the new parent id to create related rows, keep the sequence inside a transaction:
This keeps the generated id and dependent writes in one consistent unit of work.
Conflict Strategy Affects The Returned Value
The insert result is clearer with OnConflictStrategy.ABORT, because a conflict becomes an error instead of an ambiguous insert outcome.
With IGNORE, Room can return -1 for rows that were skipped due to conflict. With REPLACE, Room will insert even on conflict, but the identity behavior may not match what callers assume.
That is why many applications use ABORT when the caller truly expects "create a brand new row and give me its id."
Test The Behavior Explicitly
A small Room test is worth having:
Tests are especially useful if your app depends on a specific conflict strategy or if you later refactor the entity schema.
Common Pitfalls
One common mistake is giving a nonzero id to a new entity even though auto-generation is enabled. That can change how Room interprets the insert.
Another issue is returning Unit from the DAO method and then trying to discover the inserted row by issuing a separate query afterward.
A third problem is ignoring conflict strategy semantics. IGNORE and REPLACE can produce results that are different from "always give me the new row id."
Finally, developers sometimes assume every insert API behaves identically for single entities and lists, but the return types differ for a reason.
Summary
- Use
@PrimaryKey(autoGenerate = true)with a numeric id type such asLong. - For new entities, pass
0Las the unset id value. - Return
Longfrom a single-entity@InsertDAO method to get the generated row id. - Capture that id immediately instead of querying for "the last inserted row."
- Be deliberate about conflict strategy because it affects insert semantics and returned ids.

