MyBatis一对一映射注解@One的使用及理解

前言

本着更深入地使用注解来开发,慢慢地发现脱离了XML的MyBatis好多好多的坑。我觉得很大的原因还是来自于官方文档的不完善,以及使用注解开发持久层的人并不多见,导致网络上的相关讨论过于贫瘠并重复化,毕竟对于复杂查询的支持,我认为还没有在XML里写一条SQL方便呢~

所以这篇文章用于补充一语带过的官方文档,记录下自己趟过的坑。

正文

一对一映射

注解化一对一映射其实就是将XML中的ResultType属性对应的实体写在@Results注解中。其中的@Result填入实体的属性,而若该属性为实体中的实体,则需要@One注解引入。

1
2
3
4
5
6
7
8
9
10
11
12
@Select("select answer_id, answer_content, liked_count, create_time, question_id, user_id from answer where create_time > #{createTime} order by liked_count desc, create_time desc limit 0,10")
@Results({
@Result(id = true, column = "answer_id", property = "answerId", javaType = Integer.class),
@Result(column = "answer_content", property = "answerContent"),
@Result(column = "liked_count", property = "likedCount", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(column = "create_time", property = "createTime"),
@Result(column = "question_id", property = "question", javaType = Question.class,
one = @One(select = "selectQuestionById")),
@Result(column = "user_id", property = "user",
one = @One(select = "selectUserById"))
})
List<Answer> listAnswerByCreateTime(@Param("createTime") long createTime);

值得注意的是,映射中的property属性的值不可和其他实体属性一样,应该填写所返回的实体名称。

例如下面代码,我返回的实体为Answer类下的Question类,则property中不可写questionId,而得写question。同时@One中select属性对应的方法若在不同类,则需要写出完整的包名(com.xxx.xxx.getxxxByxx)。

1
2
@Result(column = "question_id", property = "question", javaType = Question.class,
one = @One(select = "selectQuestionById"))

需要注意的是,从@One传递过来的查询条件也需要在主查询语句中查询出来,也就是上面的listAnswerByCreateTime方法需要查询出question_id和user_id,千万别漏了。否则报你错哦!

1
2
3
4
5
6
7
@Select("select question_id, question_title from question where question_id = #{questionId}")
@ResultType(Question.class)
Question selectQuestionById(@Param("questionId") Integer questionId);

@Select("select user_id, username, avatar_url, simple_desc from user where user_id = #{userId}")
@ResultType(User.class)
User selectUserById(@Param("userId") Integer userId);

由此查询得出的结果集为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
"answerList": [
{
"answerId": 42,
"answerContent": "这是回答!",
"likedCount": 3,
"createTime": 1520508016650,
"userId": null,
"questionId": null,
"likeState": null,
"commentCount": null,
"question": {
"questionId": 1,
"questionTitle": "Spring,Django,Rails,Express这些框架技术的出现都是为了解决什么问题,现在这些框架都应用在哪些方面?",
"createTime": null,
"userId": null,
"user": null
},
"user": {
"userId": 11218,
"weiboUserId": null,
"email": null,
"username": "amosamos",
"password": null,
"joinTime": null,
"avatarUrl": "https://avatars3.githubusercontent.com/u/16012509?s=400&u=6fe0dd08943216aeff2d3c9d1b8c3e602f6de8e9&v=4"
},
"answerCommentList": null
}
]