Hi
Between version 3.4.1 and 3.4.2 (and higher) I get the following error:
Caused by: org.apache.ibatis.executor.ExecutorException: Error getting generated key or setting result to parameter object. Cause: org.apache.ibatis.executor.ExecutorException: No setter found for the keyProperty 'id' in java.lang.Class.
at org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator.processBatch(Jdbc3KeyGenerator.java:82)
at org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator.processAfter(Jdbc3KeyGenerator.java:56)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:50)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
... 4 more
Caused by: org.apache.ibatis.executor.ExecutorException: No setter found for the keyProperty 'id' in java.lang.Class.
at org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator.populateKeys(Jdbc3KeyGenerator.java:131)
at org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator.processBatch(Jdbc3KeyGenerator.java:78)
... 11 more
I have this in my mybatis config:
<setting name="useGeneratedKeys" value="true" />
And I am doing a simple annotation based update statement:
public interface BasicMapper {
@Update("update some_table set some_value = 'blah' where some_id = 1")
public int updateSomeValue();
}
This was working before, but only works if I either set the global useGeneratedKeys=false or add the following per statement: @Options(useGeneratedKeys=false). Changing either would result in wide ranging affects on our code base.
I wonder about whether this default keyProperty of "id" makes sense in MappedAnnotationBuilder, but that is not the the change that caused the problem.
See this commit in 3.4.2:
https://github.com/mybatis/mybatis-3/commit/7164f15e033c3f658df8004517f157dcdab51776 private void populateKeys(ResultSet rs, MetaObject metaParam, String[] keyProperties, TypeHandler<?>[] typeHandlers) throws SQLException {
for (int i = 0; i < keyProperties.length; i++) {
String property = keyProperties[i];
if (!metaParam.hasSetter(property)) {
throw new ExecutorException("No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + ".");
}
TypeHandler<?> th = typeHandlers[i];
if (th != null) {
Object value = th.getResult(rs, i + 1);
metaParam.setValue(property, value);
}
}
}
Which was as follows in 3.4.1:
private void populateKeys(ResultSet rs, MetaObject metaParam, String[] keyProperties, TypeHandler<?>[] typeHandlers) throws SQLException {
for (int i = 0; i < keyProperties.length; i++) {
TypeHandler<?> th = typeHandlers[i];
if (th != null) {
Object value = th.getResult(rs, i + 1);
metaParam.setValue(keyProperties[i], value);
}
}
}
While the default keyProperty of "id" was present it would never execute getResultSet because in my case type handler is null.
In my limited understanding I see 2 options:
1. Drop the default keyProperty value (might have significant affect for backwards compatibility I would guess, but can't see why it is there)
2. Or change the above to do the key property check after the type handler check:
private void populateKeys(ResultSet rs, MetaObject metaParam, String[] keyProperties, TypeHandler<?>[] typeHandlers) throws SQLException {
for (int i = 0; i < keyProperties.length; i++) {
TypeHandler<?> th = typeHandlers[i];
if (th != null) {
String property = keyProperties[i];
if (!metaParam.hasSetter(property)) {
throw new ExecutorException("No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + ".");
}
Object value = th.getResult(rs, i + 1);
metaParam.setValue(property, value);
}
}
}
Any of those changes make sense?
thanks