Replies: 4 comments 13 replies
|
Hello @chastro3 , If it works using XML, it should be possible using annotations (I think). If you have difficulty, share a repro or test case and we will look into it. |
|
Hello @harawata, I’ve looked at the example you provided, and it seems that it relies on an explicitly defined resultMap. In my case, I’ve built a generic BaseMapper on top of MyBatis Dynamic SQL, and the result mapping currently depends on MyBatis’s automatic mapping (i.e. no explicit @ConstructorArgs / @results / resultMap declarations). Because of that, no resultMap is actually declared. @Mapper
public interface QuestionBankPracticeSessionMapper extends SingleKeyBaseMapper<QuestionBankPracticeSession, QuestionBankPracticeSessionTable, Long> {
@Override
default QuestionBankPracticeSessionTable table() {
return QUESTION_BANK_PRACTICE_SESSION;
}
@Arg(javaType = QuestionBankPracticeSession.class, column = "session", columnPrefix = "s_")
@Arg(column = "answered_count", javaType = Integer.class)
@Arg(column = "correct_count", javaType = Integer.class)
@SelectProvider(type = SqlProviderAdapter.class, method = "select")
QuestionBankPracticeSessionPO selectQuestionBankPracticeSessionPO(SelectStatementProvider selectStatement);
}With this setup, attempting to use this kind of nested mapping results in an error. Are nested mappings (e.g. associations/collections) not supported when using automatic result mapping? In other words, do nested result mappings always require an explicitly declared resultMap? Thanks for the clarification! |
|
There is a known issue where we cannot express collection and association mappings with the annotations. Clinton mentioned this in the documentation he wrote about the annotations years ago. [1] The It would certainly make sense for us to revisit this and see if we could make an improvement here. To my knowledge, this is the only thing that forces XML in MyBatis. I have a Kotlin based example of nested collections using constructor mappings here: https://github.com/jeffgbutler/mybatis-kotlin-examples/tree/master/src/main/kotlin/example08 (this does require the upcoming 3.6.0 release to work). It requires XML unfortunately. |
|
Hello @harawata @jeffgbutler, This is my current solution for handling complex and nested mappings. Both User and UserSecurity are ordinary Java entities, and the aggregate result is modeled as a record: public record UserWithSecurity(
User user,
String roleIds,
UserSecurity security
) {
}To make this work, I need the following XML mappings: <resultMap id="BaseResultMap" type="top.quizbutler.model.po.User">
<constructor>
<idArg column="id" javaType="java.lang.Long" />
<arg column="user_no" javaType="java.lang.String" />
<arg column="name" javaType="java.lang.String" />
<arg column="password" javaType="java.lang.String" />
<arg column="email" javaType="java.lang.String" />
<arg column="phone" javaType="java.lang.String" />
<arg column="id_card" javaType="java.lang.String" />
<arg column="avatar" javaType="java.lang.String" />
<arg column="status" javaType="java.lang.Short" />
<arg column="banned_until" javaType="java.time.LocalDateTime" />
<arg column="remark" javaType="java.lang.String" />
<arg column="created_by" javaType="java.lang.Long" />
<arg column="updated_by" javaType="java.lang.Long" />
<arg column="created_at" javaType="java.time.LocalDateTime" />
<arg column="updated_at" javaType="java.time.LocalDateTime" />
</constructor>
</resultMap>
<resultMap id="WithSecurityResultMap" type="top.quizbutler.model.po.UserWithSecurity">
<constructor>
<arg resultMap="BaseResultMap" javaType="top.quizbutler.model.po.User" />
<arg column="role_ids" javaType="java.lang.String" />
<arg resultMap="top.quizbutler.mybatis.mapper.UserSecurityMapper.BaseResultMap"
javaType="top.quizbutler.model.po.UserSecurity"
columnPrefix="us_" />
</constructor>
</resultMap>This configuration works correctly, but it requires explicitly defining and referencing a BaseResultMap even though both User and UserSecurity are simple Java entities. For comparison, MyBatis already supports automatic mapping for simple Java beans without requiring any ResultMap: @Mapper
public interface UserMapper extends SingleKeyBaseMapper<User, UserTable, Long> {
@Override
default UserTable table() {
return USER;
}
/**
* Even without explicitly specifying a ResultMap,
* MyBatis is able to correctly map the result
* for a simple Java bean.
*/
@Override
default Optional<User> selectByPrimaryKey(Long primaryKey) {
return SingleKeyBaseMapper.super.selectByPrimaryKey(primaryKey);
}
@ResultMap("WithSecurityResultMap")
@SelectProvider(type = SqlProviderAdapter.class, method = "select")
UserWithSecurity selectUserWithSecurity(SelectStatementProvider selectStatement);
}Given that MyBatis already supports automatic mapping for ordinary Java beans, it seems unnecessary that nested constructor arguments must always reference a BaseResultMap. Ideally, the following simplified XML mapping could also be supported: <resultMap id="WithSecurityResultMap" type="top.quizbutler.model.po.UserWithSecurity">
<constructor>
<arg javaType="top.quizbutler.model.po.User" />
<arg column="role_ids" javaType="java.lang.String" />
<arg javaType="top.quizbutler.model.po.UserSecurity" columnPrefix="us_" />
</constructor>
</resultMap>And similarly for annotation-based mappings: @Arg(javaType = User.class)
@Arg(column = "role_ids", javaType = String.class)
@Arg(javaType = UserSecurity.class)
@SelectProvider(type = SqlProviderAdapter.class, method = "select")
UserWithSecurity selectUserWithSecurity(SelectStatementProvider selectStatement); |
Uh oh!
There was an error while loading. Please reload this page.
I’m using MyBatis Dynamic SQL without XML, and my domain models are mainly Java record.
Because record does not support inheritance, composition is the only way to reuse existing structures, e.g.:
However, with the current annotation-based mappings:
It’s hard to map JOIN query results into composed records.
Nested mappings usually rely on nested selects, which is not suitable for common JOIN queries.
Constructor-based mapping for composition is difficult to express with annotations.
Questions:
Is this a known limitation of annotation-based mappings?
Are there recommended patterns for JOIN + record + composition?
Thanks for your time and guidance.
All reactions