micronaut-data
micronaut-data copied to clipboard
Id column in table must be first to make @GeneratedId work with JdbcRepositories
Expected Behavior
I altered my table and now the primary key is not in the first column in the table. I'd expect that position of the ID column in the table does not matter and the ResultSet of the insert action, with the generated id is properly read.
Actual Behaviour
Value of the generated id is looked for at the first position from the ResultSet, but the id is not at the first position in the result set. An exception is thrown as the first column has a different type than the id column.
Caused by: io.micronaut.data.exceptions.DataAccessException: Error reading object for index [1] from result set: Bad value for type int : example.com
at io.micronaut.data.jdbc.mapper.ColumnIndexResultSetReader.exceptionForColumn(ColumnIndexResultSetReader.java:232)
at io.micronaut.data.jdbc.mapper.ColumnIndexResultSetReader.readInt(ColumnIndexResultSetReader.java:129)
at io.micronaut.data.jdbc.mapper.ColumnIndexResultSetReader.readInt(ColumnIndexResultSetReader.java:41)
at io.micronaut.data.runtime.mapper.ResultReader.readDynamic(ResultReader.java:111)
at io.micronaut.data.jdbc.mapper.ColumnIndexResultSetReader.readDynamic(ColumnIndexResultSetReader.java:69)
at io.micronaut.data.jdbc.mapper.ColumnIndexResultSetReader.readDynamic(ColumnIndexResultSetReader.java:41)
at io.micronaut.data.jdbc.operations.DefaultJdbcRepositoryOperations$JdbcEntityOperations.execute(DefaultJdbcRepositoryOperations.java:958)
An easy solution would be to use identity.getName() to get the id value from the ResultSet instead of the fixed 1. Problematic code part:
// DefaultJdbcRepositoryOperations.java
if (hasGeneratedId) {
try (ResultSet generatedKeys = ps.getGeneratedKeys()) {
if (generatedKeys.next()) {
RuntimePersistentProperty<T> identity = persistentEntity.getIdentity();
Object id = columnIndexResultSetReader.readDynamic(generatedKeys, 1, identity.getDataType());
BeanProperty<T, Object> property = (BeanProperty<T, Object>) identity.getProperty();
entity = updateEntityId(property, entity, id);
} else {
throw new DataAccessException("Failed to generate ID for entity: " + entity);
}
}
}
Steps To Reproduce
create table example
(
domain varchar(128) not null,
id serial primary key,
geoname_id integer
);
@MappedEntity
@Data
public class Example {
@Id
@GeneratedValue
private Integer id;
private String domain;
@Nullable
private Integer geonameId;
}
@JdbcRepository(dialect = POSTGRES)
public interface ExampleRepo extends PageableRepository<Example, Integer> {
}
Environment Information
Jdk17
Example Application
No response
Version
3.5.3