简介
在前一篇文章里我们已经讨论了一个简单的基于xml配置文件运行mybatis的示例。实际上,要完成上述的功能,mybatis里还提供了一种基于annotation的实现方式。对于有些不喜欢繁琐的xml配置文件的人来说,这种方式因为是添加标注到代码里,并不会带来实现上的侵入。总的来说,这种方式会显得稍微简洁一点。
项目修改
结合前面那个项目来看,我们通过xml配置的重点在两个地方,一个是mapper-config.xml文件这里。它主要是配置访问数据库的不同环境和对应的数据源。基本上整个项目就一个这样的文件。还有一个就是针对不同mapper接口对应的mapper xml文件。在实际项目里,我们可能需要根据需要定义若干个接口,而每个接口都需要有一个对应的xml文件。实际上,如果我们能够在定义mapper接口的地方就能把这个映射关系给定义好的话,这样实现就显得更紧凑,而不用在接口代码和配置中来回比较。
现在,我们就看看对原来的工程该怎么修改吧。在原来的工程中,mapper-config.xml里有这么一部分配置,是用来指定mapper文件的:
采用这种方式指定的是具体的某个xml文件,当有多个xml映射文件的话,这种方式就显得比较繁琐了。尤其是在有多个mapper接口定义好的情况下。这样,我们可以将上面这部分修改成如下:
这种配置方式显得很java:)。之所以这么说是因为这种指定package配置项的方式有点像spring里的componentscan。这里有点类似的意思,就是让mybatis在给定的mappers java包里头找所有的mapper接口。这在有多个映射接口的情况下确实简洁了不少。剩下的部分就是将原来xml里的配置信息用annotation的方式给描述出来。
select
关于select的实现,在这里有专门的Select annotation,在它的参数里可以提供对应的sql操作语句。像本示例中有getUserById和getAllUsers两个方法。它们的详细实现如下:
@Select("SELECT user_id as userId, email_id as emailId, password, first_name as firstName, last_name as lastName FROM user WHERE USER_ID = #{userId}")
public User getUserById(Integer userId);
@Select("select * from user")
@Results({
@Result(id=true, column="user_id", property="userId"),
@Result(column="email_id", property="emailId"),
@Result(column="password", property="password"),
@Result(column="first_name", property="firstName"),
@Result(column="last_name", property="lastName")
})
public List getAllUsers();
这部分的实现比较有意思。除了在原来定义的annotation里设置sql代码,在某些情况下因为我们还需要有对象关系的映射。在xml文件里是有一个resultMap项,在这里则有@Results, @Result的标记项。其中@Results作用于某个方法的时候,就表示它就是该方法所映射的resultMap。很显然,@Result则是里面每个具体元素的映射项。
这里还有一个值得注意的地方,在前面xml配置的工程里,一旦定义好了一个resultMap的映射之后,它在多个查询的方法里是可以复用的,但是在基于annotation的方式里则不行。比如说上述的代码里,如果我们希望将getUserById的方法该成也使用resultMap的方式的话,有两种方式,一种就是把getAllUsers方法里的配置在前面再重复一遍。还有一种就是把resultMap的定义放到原来的mapper xml文件中,而其他的部分还是留在代码里。这种方法的修改如下:
原来的xml文件只剩下resultMap这部分。然后对应的mapper接口如下:
@Select("select * from user")
@ResultMap("com.yunzero.mybatisSample.mappers.UserMapper.UserResult")
public List getAllUsers();
insert
insert的过程也比较简单,和前面xml配置的方式类似,它的详细实现如下:
@Insert("INSERT INTO user(email_id, password, first_name, last_name) VALUES(#{emailId}, #{password}, #{firstName}, #{lastName})")
@Options(useGeneratedKeys=true, keyProperty="userId")
public void insertUser(User user);
在这个示例里,尤其是针对需要数据库自动生成id的,我们用对应的Options标记来设置这两个属性。剩下的就完全一样了。
update, delete
关于update和delete的过程,可以说基本上就是照搬原来的过程了,它的详细实现如下:
@Update("UPDATE user SET PASSWORD= #{password}, FIRST_NAME = #{firstName},LAST_NAME = #{lastName} WHERE USER_ID = #{userId}")
public void updateUser(User user);
@Delete("DELETE FROM user WHERE USER_ID = #{userId}")
public void deleteUser(Integer userId);
这里的一个基本的规律就是xml里的select, insert, update, delete项,这里就有对应的annotation项。
这样,整个项目的修改就完成了。详细的实现可以参照附件里的代码。
总结
基于annotation的配置方式和基于xml的方式比起来显得更加紧凑一些,但是它在对resultMap的复用上显得表达力有点不足。这两种方式各有自己的优缺点,可以针对各自的情况来选择。
参考材料
java persistence with mybatis 3