【MyBatis】 MyBatis修炼之八 MyBatis 注解方式的基本用法

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


上一篇:【MyBatis】 MyBatis修炼之七 MyBatis XML方式的基本用法(多个接口参数)

下一篇:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容