Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPE in DefaultResultSetHandler when using association on composite key #1590

Closed
nboissel opened this issue Jul 3, 2019 · 7 comments

Comments

@nboissel
Copy link

commented Jul 3, 2019

MyBatis version

3.3.0+
(example and lines below are based on the 3.5.1)

Database vendor and version

PostgreSQL 9.6 or H2 1.4

Steps to reproduce

  1. Have an association in a mapper based on a composite key
  2. Use any request using the resultMap

Mapper example:

<mapper namespace="my.package.VariableMapper">
	<resultMap id="BaseResultMap" type="VariableImpl">
		<id column="va_process_id" property="processId" jdbcType="INTEGER" />
		<id column="va_variable_id" property="variableId" jdbcType="VARCHAR" />
		[...]
	</resultMap>
	
	<resultMap id="CompleteResultMap" type="VariableImpl" extends="BaseResultMap">
		<association property="linkedVariable" column="{processId=lv_va_process_id,variableId=lv_va_variable_id}"
			javaType="VariableImpl" resultMap="my.package.VariableMapper.BaseResultMap" columnPrefix="lv_"/>
		[...]
	</resultMap>
[...]
</mapper>

Expected result

The request done, as in 3.2.8-

Actual result

NPE on DefaultResultSetHandler L472 with typeHandler as null

Cause: java.lang.NullPointerException
	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:149)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:87)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58)
	at com.sun.proxy.$Proxy44.selectById(Unknown Source)
	[...]
Caused by: java.lang.NullPointerException
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getPropertyMappingValue(DefaultResultSetHandler.java:472)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.applyPropertyMappings(DefaultResultSetHandler.java:441)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:905)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForNestedResultMap(DefaultResultSetHandler.java:870)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:326)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:301)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:194)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
	at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
	at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:324)
	at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:83)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
	... 36 more

The problem seems to comes from this commit : 9d29135
where those three lines were deleted :
if (composites.size() > 0) { column = null; }
In case of composite column, the value of this property is then keept instead of removed and the treatment is done as it was a simple column and not a composite one so the typeHandler is null as there is no real data behind this propertyMapping.

Best regards,

Nicolas

@harawata

This comment has been minimized.

Copy link
Member

commented Jul 3, 2019

Thanks for the report, @nboissel !
Could you provide a test case or demo project using a minimum set of tables and columns?
We need to add a test case to avoid future regression.

nboissel pushed a commit to nboissel/mybatis-issues that referenced this issue Jul 4, 2019

@nboissel

This comment has been minimized.

Copy link
Author

commented Jul 4, 2019

No problem.

Here is a test case to reproduce the issue : nboissel/mybatis-issues@5de4a0d

It works fine with 3.2.8 but throw a NPE using any 3.5.1 version.

Best regards,

Nicolas

@harawata

This comment has been minimized.

Copy link
Member

commented Jul 4, 2019

Thanks for the repro, @nboissel !

In your usage, column attribute is not used, so just removing column should resolve the NPE.
In the issue description, columnPrefix is specified and that is the attribute you need to make this mapping work.

Anyway, MyBatis should not throw NPE when unnecessary column attribute is specified.
I'll fix it tomorrow.

@nboissel

This comment has been minimized.

Copy link
Author

commented Jul 5, 2019

My example is maybe confusing because I used composite key association on the same table to avoid creating a second table.

As I understand that (and used it in my project since a while), the columnPrefix is used to avoid name conflicts during mapping while using the same column name, which is the case while referencing the same table (e.g. a user and his manager).

I used in my example the prefix child_ in the fields to make it easily understandable but I don't understand how I can map a composite key in an association without the column="{prop1=col1,prop2=col2}" format explained in the documentation (http://www.mybatis.org/mybatis-3/sqlmap-xml.html#Result_Maps in "Nested Select for Association" section).

If its too confusing or if I'm not clear, I can make my test case bigger, using a second table to show the composite key use in a more classical way.

@harawata

This comment has been minimized.

Copy link
Member

commented Jul 5, 2019

There is no select attribute in any of the <association /> elements you provided.
If that is not the result of oversimplification, your case is "Nested Results for Association" (the next section in the doc).
With "nested results", composite key mapping is done in the query (e.g. in ON clause of join condition).

If it's still unclear, creating more realistic example might help make things clearer for both of us indeed. :)

@nboissel

This comment has been minimized.

Copy link
Author

commented Jul 5, 2019

You're right, I misunderstood the configuration (certainly some old tests kept in my mapper).
Thanks for the explanation.

I keep the issue open as this is always good to fix a possible NPE.

@harawata harawata closed this in 3becd0a Jul 5, 2019

@harawata

This comment has been minimized.

Copy link
Member

commented Jul 5, 2019

The NPE should be resolved in the latest 3.5.2-SNAPSHOT (i.e. the column will be silently ignored).
Thanks again for your help, @nboissel !

@harawata harawata self-assigned this Jul 5, 2019

@harawata harawata added this to the 3.5.2 milestone Jul 5, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.