MyBatis注解方式就是将SQL语句直接写在接口上,这种方法的有点是,对于需求比较简单的系统,效率高,缺点是,当SQL有变化时都需要重新编译代码,一般情况下,不建议使用注解方式。
MyBatis参考文档:
中文版:http://www.mybatis.org/mybatis-3/zh/index.html
英文版:http://www.mybatis.org/mybatis-3/
工具
JDK 1.6及以上版本
MyBatis 3.30版本
MySQL 6.3版本
Eclipse4 及以上版本
Apache Maven 构建工具
项目源码下载地址:https://github.com/JFAlex/MyBatis/tree/master/MyBatis_No.8
使用注解就是在接口方法基础上添加需要的注解,并写上相关的SQL语句,@Select 、@Insert 、@Update 和@Delete 这4个基本注解的参数可以是字符串数组类型,也可以是字符串类型。
@Select 注解
我们现在有个接口方法的作用是根据用户id,查询用户的信息,则我们只需要在接口方法之前添加注解:
@Select({"select id,user_name userName,user_password userPassword,user_email userEmail,user_info userInfo,head_img headImg,create_time createTime from sys_user where id = #{id}"})
public SysUser selectById(Long id);
使用注解方式我们也需要考虑表字段和JavaBean属性字段的映射问题。在注解方式中,我们有三种方式来实现字段映射关系。
第一种:通过SQL语句使用别名来实现,别名为JavaBean中的属性字段
上面我们使用的就是此方式。
第二种:使用mapUnderscoreToCamelCase配置
在数据库中,由于大多数数据库设置不区分大小写,因此下划线方式的命名很常见,如user_name 、user_password 、user_email 。在Java中,一般都使用驼峰命名方式,如userName、userPassword、userEmail。因为数据库和Java中的这两种命名方式很常见,因此MyBatis还提供了一个全局属性mapUnderscoreToCamelCase,通过配置这个属性为true可以将以下划线方式命名的数据库列映射到Java对象的驼峰式命名属性中,这个属性默认为false,如果想要使用该配置,我们只需要在MyBatis的配置文件中增加如下配置
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
使用这种配置方式,我们就不再需要手动指定别名了,MyBatis字段“下划线转驼峰”的方式自动映射,@Select注解中的SQL可以写成
@Select({"select * from sys_user where id = #{id}"})
或
@Select({"select id,user_name userName,user_password userPassword,user_email userEmail,user_info userInfo,head_img headImg,create_time createTime from sys_user where id = #{id}"})
第三种:使用resultMap方式
XML中的resultMap元素有一个对应的Java注解@Results,我们也可以使用这个注解来实现字段映射关系。
@Results(id="userResultMap", value={
@Result( property="id", column="id" ,id=true),
@Result( property="userName", column="user_name" ),
@Result( property="userPassword" ,column="user_password" ),
@Result( property="userEmail", column="user_email" ),
@Result( property="userInfo" ,column="user_info" ),
@Result( property="headImg" ,column="head_img" , jdbcType=JdbcType.BLOB ),
@Result( property="createTime" ,column="create_time" ,jdbcType=JdbcType.TIMESTAMP )
})
//@Select({"select id,user_name userName,user_password userPassword,user_email userEmail,user_info userInfo,head_img headImg,create_time createTime from sys_user where id = #{id}"})
@Select({"select * from sys_user where id = #{id}"})
public SysUser selectById(Long id);
这里的@Result注解对应着XML文件中的<result>元素,其中参数中添加 id=true ,就对应<id>元素。
如果我们在多个方法中都要使用到这个@Results,那么我们只需要为@Results注解添加一个id属性(MyBatis3.3.1版本开始提供此属性)设置了id属性后,就可以通过id属性值来引用同一个@Results配置了
/**
* 查询所有用户信息
*
* @return
*/
@ResultMap("userResultMap")
@Select({"select * from sys_user"})
public List<SysUser> selectAll();
如果我们配置XML一起使用,则我们只需要引用XML中<resultMap>元素的id属性值。
测试selectById,输出日志:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 495792375.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d8d30f7]
DEBUG [main] - ==> Preparing: select * from sys_user where id = ?
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, admin@mybais.alex, <<BLOB>>, <<BLOB>>, 2017-08-09 15:26:52.0
DEBUG [main] - <== Total: 1
SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@mybais.alex, userInfo=管理员, headImg=null, createTime=Wed Aug 09 15:26:52 CST 2017]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d8d30f7]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d8d30f7]
DEBUG [main] - Returned connection 495792375 to pool.
测试selectAll,输出日志
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 495792375.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d8d30f7]
DEBUG [main] - ==> Preparing: select * from sys_user
DEBUG [main] - ==> Parameters:
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, admin@mybais.alex, <<BLOB>>, <<BLOB>>, 2017-08-09 15:26:52.0
TRACE [main] - <== Row: 2, test, 123456, test@mybais.alex, <<BLOB>>, <<BLOB>>, 2017-08-09 15:27:30.0
DEBUG [main] - <== Total: 2
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d8d30f7]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d8d30f7]
DEBUG [main] - Returned connection 495792375 to pool.
@Insert 注解
使用@Insert注解时,我们注意需要注意的是返回主键值的情况,如果不需要返回主键值,则@Insert注解的使用是非常简单的。
不需要返回主键
如果我们需要返回主键,那么使用注解时SQL和XML中的SQL完全一样
/**
* 保存新用户信息
*
* @param sysUser
* @return
*/
@Insert({"INSERT INTO sys_user (id,user_name, user_password,user_email, user_info, head_img, create_time) VALUES(#{id},#{userName},#{userPassword},#{userEmail},#{userInfo},#{headImg, jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})"})
public int insert(SysUser sysUser);
返回自增主键
如果我们数据库中的主键字段是自增的方式生成的,那么我们除了必须的@Insert注解外,还需要添加一个@Option注解
/**
* 保存新用户信息,并返回主键
*
* @param sysUser
* @return
*/
@Insert({"INSERT INTO sys_user (user_name, user_password,user_email, user_info,head_img, create_time)VALUES (#{userName},#{userPassword},#{userEmail},#{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})"})
@Options(useGeneratedKeys=true,keyProperty="id")
public int insert2(SysUser sysUser);
和不返回主键的insert方法相比,insert2方法中的SQL中少了id列,而且多使用一个@Option注解,我们在这个注解中设置了useGeneratedKeys和keyProperty属性,用法和XML相同,当我们要配置多个列时,这个注解也提供了keyColumn属性,可以像XML中一样配置使用。
返回非自增主键
如果我们数据库中的主键不是自增方式产生的,但是当我们插入新数据后,需要返回该条数据的主键,那么我们可以使用如下方法:
/**
* 保存新用户信息,并返回主键
*
* @param sysUser
* @return
*/
@Insert({"INSERT INTO sys_user (id,user_name, user_password,user_email,user_info, head_img, create_time)VALUES(#{id},#{userName},#{userPassword},#{userEmail},#{userInfo},#{headImg, jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})"})
@SelectKey(statement="SELECT LAST_INSERT_ID()",
keyProperty="id",
resultType=Long.class,
before=false)
public int insert3(SysUser sysUser);
使用@SelectKey注解,以下代码是使用XML配置时的selectKey。
<selectKey keyColumn="id" resultType="long" keyProperty="id"
order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
注解方式和XML方式配置的属性基本相同,其中before为false时功能等同于order=”AFTER”,before=true时功能等同于order=”BEFORE”。
注意:在不同的数据库中,order的配置不同
order属性的设置和使用的数据库有关。在MySQL数据库中,order属性设置的值是AFTER,因为当前记录的主键是在insert语句执行成功后才获取到的。而在Oracel数据库中,order属性的值要设置为BEFORE,这是因为Oracle数据库中需要先从序列获取值,然后将值作为主键插入到数据库中。
@Update注解和@Delete注解
@Update注解和@Delete注解使用都很简单,不多做说明:
@Update注解
/**
* 根据用户id,修改用户信息
*
* @param sysUser
* @return
*/
@Update({"update sys_user set user_name = #{userName},user_password = #{userPassword},user_email = #{userEmail}, user_info = #{userInfo}, head_img = #{headImg , jdbcType=BLOB}, create_time = #{createTime,jdbcType=TIMESTAMP} where id = #{id}"})
public int updateById(SysUser sysUser);
@Delete注解
/**
* 根据用户id,删除用户信息
*
* @param id
* @return
*/
@Delete({"delete from sys_user where id = #{id}"})
public int deleteById(Long id);
注意:我们在使用MyBatis注解方式时,可以不使用Mapper.xml配置文件,也可以和Mapper.xml配合使用。不管我们采用何种方式,我们都必须在MyBatis的配置文件中添加
<mappers>
<package name="mybatis.simple.mapper"/>
</mappers>
用来指定接口类的位置,如果同时使用Mapper.xml,那么我们的Mapper.xml文件也必须在此配置包下(Mapper.xml可以放在src/main/java下,也可以放在src/main/resources下)
MyBatis的注解方式并不是主流,因此不做过多说明。
项目源码下载地址:https://github.com/JFAlex/MyBatis/tree/master/MyBatis_No.8