Skip to content

Cascade Error with <Constructor> resulting in null value #1191

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

Closed
christopherpicard opened this issue Feb 15, 2018 · 7 comments
Closed

Cascade Error with <Constructor> resulting in null value #1191

christopherpicard opened this issue Feb 15, 2018 · 7 comments

Comments

@christopherpicard
Copy link

There is a cascade issue where a value is not getting set if you are using constructor options. If you have an entity that uses the result map form of a constructor argument, and in the content of that result map there is a nested result map for an association or collection, the value is always null. See attached code example zip.

MyBatis version

3.4.4

Database vendor and version

MSSql 2008 r2

Test case or example project

errorSample.zip

Steps to reproduce

Run SampleExecutor.

Expected result

Output of pass as the retrieved and original objects will match.

Actual result

Output of fails because the value distance is null in result.

@harawata
Copy link
Member

Thanks for the report, @christopherpicard .
It probably is a duplicate of #101 . Could you clarify?

@christopherpicard
Copy link
Author

Does not look like a duplicate to me, in fact the workaround to this issue is to create an all arg private constructor which includes collections in my real code which works correctly. The root of this issue is more that for some reason it is not executing the nestedResult map from what I observed in the debugger.

@harawata
Copy link
Member

Okay, I may be missing something, then.
I (or someone) will look into it.
Thanks for the demo, by the way!

@harawata
Copy link
Member

The demo is a little bit too complicated, but the core issue is that sample3Dao.selectBySample2Id() returns an instance of Sample3, but its property distance is null, right?
This is because the distance is mapped as a nested result which is not supported (#101 is the ticket requesting this enhancement).

<resultMap id="sample3BuilderResultMap" type="Sample3Builder">
  <result property="testString3" column="TestString3" javaType="String"/>
  <association property="distance" resultMap="distanceResultMap"/>
</resultMap>

Please let me know if you think I am still misunderstanding the problem.

@christopherpicard
Copy link
Author

christopherpicard commented Feb 19, 2018

Yeah, the demo can be simplified if needed, at the time I built it I was not 100% sure of the issue so i tried to mimic my actual code as closely as possible. Yes the core issue is that selecteBySample2Id() returns an instance of sample3 with the distance property of null. Think you would see the same issue if you drop sample 3 all together and make distance a property of sample 2 if that makes it easier.

I guess I am not understanding 101 fully if you think it is a duplicate. It talks explicitly about the constructor arg which does actually work for me. If you replace the sample3ResultMap with the following:

<resultMap id="sample3ResultMap" type="Sample3">
  <constructor>
    <arg column="TestString3" javaType="String"/>
    <arg resultMap="distanceResultMap" javaType="Distance"/>
  </constructor>
</resultMap>

and add a constructor to Sample3 to take both arguments, it works perfectly which seems to be what is asked for in 101. The issue for me is some objects can have a significant amount of parameters that the constructors are messy and hard to maintain vs having the one single constructor to fully support the builder pattern.

@harawata
Copy link
Member

In your original demo, sample3BuilderResultMap contains <association /> of type nested results [1].
Currently, this result map does not work if it's referenced from <idArg /> or <arg /> and #101 is the enhancement request to support it.
The technical difficulties were discussed on #101.

If you replace the sample3ResultMap with the following: (...) and add a constructor to Sample3 to take both arguments, it works perfectly

It works because no <association /> is involved anymore.

It also seems to be working if <association /> type is nested select (it could cause N+1 problem, though).

<resultMap id="sample3BuilderResultMap" type="Sample3Builder">
  <result property="testString3" column="TestString3" javaType="String" />
  <association property="distance" select="selectDistance" column="Sample2Id" />
</resultMap>

<select id="selectDistance" resultMap="distanceResultMap">
  select Distance, DistanceUnit from Sample3s where Sample2Id = #{id} 
</select>

[1] There are two types of <association /> (or <collection />) : nested select and nested results.
Simply put, the one that has select attribute is nested select.
http://www.mybatis.org/mybatis-3/sqlmap-xml.html#association

@harawata
Copy link
Member

Closing as a duplicate of #101 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants