【MyBatis】 MyBatis修炼之八 MyBatis

作者: 开心跳蚤 | 来源:发表于2017-08-30 16:53 被阅读337次

    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方式的基本用法(多个接口参数)

    下一篇:

    相关文章

      网友评论

      • LinkedIn:@Results 注解中的 id 值 在eclipse 中报错 看了dtd 文件不允许定义id值
        LinkedIn: @开心跳蚤 ok
        开心跳蚤:@LinkedIn mybatis版本的问题,3.3.1版本及之后的版本才可以定义id,你看下你的版本,我文中有提到

      本文标题:【MyBatis】 MyBatis修炼之八 MyBatis

      本文链接:https://www.haomeiwen.com/subject/sfzorxtx.html