[
https://issues.apache.org/jira/browse/IBATISNET-206?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12472555
]
Ihar Bury commented on IBATISNET-206:
-------------------------------------
I've uploaded a possible fix we used for our development.
We added an attribute to <result> element called notNullColumn. It should be
set to a name of column that cannot be null in a referenced result map.
<resultMap id="ConsumptionHistoryUsers" class="User" groupBy="Id">
<result property="Id" column="id" />
...
<result property="filteredTopContentConsumptionHistory"
resultMapping="UserMap.ConsumptionHistoryUsersContent"
notNullColumn="content_id" />
</resultMap>
<resultMap id="ConsumptionHistoryUsersContent" class="Content">
<result property="Id" column="content_id" />
<result property="Creator"
resultMapping="UserMap.ConsumptionHistoryUsersContentCreator" />
<result property="DateCreated" column="content_date_created" />
<result property="Title" column="content_title" />
<discriminator type="int" column="content_subtype_id" />
<subMap value="5" resultMapping="ConsumptionHistoryUsersBlog" />
</resultMap>
<resultMap id="ConsumptionHistoryUsersBlog" class="BlogContent"
extends="UserMap.ConsumptionHistoryUsersContent">
</resultMap>
> groupBy incorrectly handles left outer join results where right part is empty
> -----------------------------------------------------------------------------
>
> Key: IBATISNET-206
> URL: https://issues.apache.org/jira/browse/IBATISNET-206
> Project: iBatis for .NET
> Issue Type: Bug
> Components: DataMapper
> Affects Versions: DataMapper 1.6
> Reporter: Ihar Bury
> Attachments: GroupByStrategy.cs, ResultProperty.cs,
> ResultPropertyDeSerializer.cs, SqlMap.xsd
>
>
> We use the newly added groupBy functionality as follows:
> <resultMap id="ConsumptionHistoryUsers" class="User"
> groupBy="Id">
> <result property="Id" column="id" />
> ...
> <result property="filteredTopContentConsumptionHistory"
> resultMapping="UserMap.ConsumptionHistoryUsersContent" />
> </resultMap>
> <resultMap id="ConsumptionHistoryUsersContent" class="Content">
> <result property="Id" column="content_id" />
> <result property="Creator"
> resultMapping="UserMap.ConsumptionHistoryUsersContentCreator" />
> <result property="DateCreated"
> column="content_date_created" />
> <result property="Title" column="content_title" />
> <discriminator type="int" column="content_subtype_id" />
> <subMap value="5"
> resultMapping="ConsumptionHistoryUsersBlog" />
> </resultMap>
> <resultMap id="ConsumptionHistoryUsersBlog" class="BlogContent"
> extends="UserMap.ConsumptionHistoryUsersContent">
> </resultMap>
> The result map is for select SQL like
> select *
> from User
> left outer join Content on ...
> This works well in the cases where each selected User has at least one
> Content joined to it. But when there is one User that doesn't have any
> corresponding content, a failure occurs. The record returned from the
> database has values for User and has null values for all Content columns.
> iBATIS should just store an empty collection to the resulting User object in
> this case but it tries to load all those nulls as a Content object. In our
> case that ends up with NullReferenceException while analizing the
> discriminator value.
> subMap = _discriminator.GetSubMap(
> dataBaseValue.ToString() );
> where dataBaseValue == null
> >
> > IBatisNet.DataMapper.dll!IBatisNet.DataMapper.Configuration.ResultMapping.ResultMap.ResolveSubMap(System.Data.IDataReader
> > dataReader = {IBatisNet.DataMapper.Commands.DataReaderDecorator}) Line 444
> > C#
>
> IBatisNet.DataMapper.dll!IBatisNet.DataMapper.MappedStatements.PropertStrategy.GroupByStrategy.Get(IBatisNet.DataMapper.Scope.RequestScope
> request = {IBatisNet.DataMapper.Scope.RequestScope},
> IBatisNet.DataMapper.Configuration.ResultMapping.IResultMap resultMap =
> {IBatisNet.DataMapper.Configuration.ResultMapping.ResultMap},
> IBatisNet.DataMapper.Configuration.ResultMapping.ResultProperty mapping =
> {IBatisNet.DataMapper.Configuration.ResultMapping.ResultProperty}, ref object
> target = {Tw.Core.BusinessLayer.ObjectModel.Users.User},
> System.Data.IDataReader reader =
> {IBatisNet.DataMapper.Commands.DataReaderDecorator}) Line 99 + 0x19 bytes
> C#
>
> IBatisNet.DataMapper.dll!IBatisNet.DataMapper.MappedStatements.PropertStrategy.GroupByStrategy.Set(IBatisNet.DataMapper.Scope.RequestScope
> request = {IBatisNet.DataMapper.Scope.RequestScope},
> IBatisNet.DataMapper.Configuration.ResultMapping.IResultMap resultMap =
> {IBatisNet.DataMapper.Configuration.ResultMapping.ResultMap},
> IBatisNet.DataMapper.Configuration.ResultMapping.ResultProperty mapping =
> {IBatisNet.DataMapper.Configuration.ResultMapping.ResultProperty}, ref object
> target = {Tw.Core.BusinessLayer.ObjectModel.Users.User},
> System.Data.IDataReader reader =
> {IBatisNet.DataMapper.Commands.DataReaderDecorator}, object keys = null) Line
> 71 + 0x15 bytes C#
>
> IBatisNet.DataMapper.dll!IBatisNet.DataMapper.MappedStatements.ResultStrategy.GroupByStrategy.Process(IBatisNet.DataMapper.Scope.RequestScope
> request = {IBatisNet.DataMapper.Scope.RequestScope}, ref
> System.Data.IDataReader reader =
> {IBatisNet.DataMapper.Commands.DataReaderDecorator}, object resultObject =
> null) Line 88 + 0x2e bytes C#
>
> IBatisNet.DataMapper.dll!IBatisNet.DataMapper.MappedStatements.ResultStrategy.MapStrategy.Process(IBatisNet.DataMapper.Scope.RequestScope
> request = {IBatisNet.DataMapper.Scope.RequestScope}, ref
> System.Data.IDataReader reader =
> {IBatisNet.DataMapper.Commands.DataReaderDecorator}, object resultObject =
> null) Line 64 + 0x14 bytes C#
>
> IBatisNet.DataMapper.dll!IBatisNet.DataMapper.MappedStatements.MappedStatement.RunQueryForList<Tw.Core.BusinessLayer.ObjectModel.Users.User>(IBatisNet.DataMapper.Scope.RequestScope
> request = {IBatisNet.DataMapper.Scope.RequestScope},
> IBatisNet.DataMapper.ISqlMapSession session =
> {IBatisNet.DataMapper.SqlMapSession}, object parameterObject =
> {Tw.Core.DataLayer.Mappers.Users.UserMapper.UserConsumptionHistoryUsersParams},
>
> System.Collections.Generic.IList<Tw.Core.BusinessLayer.ObjectModel.Users.User>
> resultObject = null,
> IBatisNet.DataMapper.RowDelegate<Tw.Core.BusinessLayer.ObjectModel.Users.User>
> rowDelegate = null) Line 768 + 0x17 bytes C#
>
> IBatisNet.DataMapper.dll!IBatisNet.DataMapper.MappedStatements.MappedStatement.ExecuteQueryForList<Tw.Core.BusinessLayer.ObjectModel.Users.User>(IBatisNet.DataMapper.ISqlMapSession
> session = {IBatisNet.DataMapper.SqlMapSession}, object parameterObject =
> {Tw.Core.DataLayer.Mappers.Users.UserMapper.UserConsumptionHistoryUsersParams})
> Line 643 + 0x45 bytes C#
>
> IBatisNet.DataMapper.dll!IBatisNet.DataMapper.SqlMapper.QueryForList<Tw.Core.BusinessLayer.ObjectModel.Users.User>(string
> statementName = "GetUserConsumptionHistoryUsers", object parameterObject =
> {Tw.Core.DataLayer.Mappers.Users.UserMapper.UserConsumptionHistoryUsersParams})
> Line 1019 + 0x40 bytes C#
> In a case without discriminator and subclasses, iBATIS attempts to create an
> object with all values set to NULL, that is also incorrect.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.