Mybatis之旅第二篇-Mapper动态代理方式

一、引言

通过上一篇mybatis的入门学习,我们已经会使用mybatis实现简单的增删改查,但是我们也发现了用原始Dao开发的一些问题:

Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法

调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护。

为了解决这些问题,我们采用Mapper动态代理方法来进行开发:程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

二、开发规范

Mapper接口开发需要遵循以下规范:

1、 Mapper.xml文件中的namespace与mapper接口的类路径相同。

2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同

3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

4、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

三、改造

第一步:Mapper.xml(映射文件)

定义mapper映射文件UserMapper.xml,将UserMapper.xml放在config下mapper目录下,效果如下:

文件内容如下:

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper

        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

        "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 --><mapper namespace="com.yuanqinnan.mapper.UserMapper"><select id="queryUserById" parameterType="int" resultType="com.yuanqinnan.model.User">    SELECT * FROM `user`where id=#{id}

  </select><!-- 查询 user 表的所有数据--><select id="selectUserAll" resultType="com.yuanqinnan.model.User">        select * from user

    </select><!--            1、${value}里面必须要写value,不然会报错

            2、${}表示拼接 sql 字符串,将接收到的参数不加任何修饰拼接在sql语句中

            3、使用${}会造成 sql 注入

    --><select id="selectLikeUserName" resultType="com.yuanqinnan.model.User" parameterType="String">        select * from user where username like '%${value}%'

    </select><!--#{}实现--><select id="selectLikeUserName2" resultType="com.yuanqinnan.model.User" parameterType="String">        select * from user where username like #{username}

    </select><!-- 向 user 表插入一条数据 --><insert id="insertUser" parameterType="com.yuanqinnan.model.User">        insert into user(id,username,sex,birthday,address)

            value(#{id},#{username},#{sex},#{birthday},#{address})

    </insert><!-- 保存用户 --><insert id="saveUser" parameterType="com.yuanqinnan.model.User"><!-- selectKey 标签实现主键返回 --><!-- keyColumn:主键对应的表中的哪一列 --><!-- keyProperty:主键对应的pojo中的哪一个属性 --><!-- order:设置在执行insert语句前执行查询id的sql,在执行insert语句之后执行查询id的sql --><!-- resultType:设置返回的id的类型 --><selectKey keyColumn="id" keyProperty="id" order="AFTER"                  resultType="int">            SELECT LAST_INSERT_ID()

        </selectKey>        INSERT INTO `user`

        (username,birthday,sex,address) VALUES

        (#{username},#{birthday},#{sex},#{address})

    </insert><!-- 根据 id 更新 user 表的数据 --><update id="updateUserById" parameterType="com.yuanqinnan.model.User">        update user set username=#{username} where id=#{id}

    </update><!-- 根据 id 删除 user 表的数据 --><delete id="deleteUserById" parameterType="int">        delete from user where id=#{id}

    </delete></mapper>

其他地方未有改动,主要是namespace="com.yuanqinnan.mapper.UserMapper"的修改,现在我们实现这个接口

第二步:UserMapper(接口文件)

新建mapper包,新增接口UserMapper

内容:

publicinterface UserMapper {

    //查询用户User queryUserById(int id);

    //查询用户列表List selectUserAll();

    //模糊查询List selectLikeUserName(String username);

    //新增void saveUser(User user);


}

第三步:加载UserMapper.xml文件

<mappers><!-- 映射文件方式1,一个一个的配置--><mapper resource="config/sqlmap/User.xml"/><mapper resource="config/mapper/UserMapper.xml"/></mappers>

测试:

publicclass MapperTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before

    publicvoidinit()throws Exception {

        // 创建SqlSessionFactoryBuilderSqlSessionFactoryBuilder sqlSessionFactoryBuilder =new SqlSessionFactoryBuilder();

        // 加载SqlMapConfig.xml配置文件InputStream inputStream = Resources.getResourceAsStream("config/SqlMapConfig.xml");

        // 创建SqlsessionFactorythis.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    }

    @Test

    publicvoid testQueryUserById() {

        // 获取sqlSession,和spring整合后由spring管理SqlSession sqlSession =this.sqlSessionFactory.openSession();

        // 从sqlSession中获取Mapper接口的代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        // 执行查询方法User user = userMapper.queryUserById(1);

        System.out.println(user);

        // 和spring整合后由spring管理        sqlSession.close();

    }

    @Test

    publicvoid testQueryUserByUsername() {

        // 获取sqlSession,和spring整合后由spring管理SqlSession sqlSession =this.sqlSessionFactory.openSession();

        // 从sqlSession中获取Mapper接口的代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        // 执行查询方法List list = userMapper.selectLikeUserName("张");

        for (User user : list) {

            System.out.println(user);

        }

        // 和spring整合后由spring管理        sqlSession.close();

    }

    @Test

    publicvoid testSaveUser() {

        // 获取sqlSession,和spring整合后由spring管理SqlSession sqlSession =this.sqlSessionFactory.openSession();

        // 从sqlSession中获取Mapper接口的代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        // 创建保存对象User user =new User();

        user.setUsername("刘备");

        user.setBirthday(new Date());

        user.setSex("1");

        user.setAddress("蜀国");

        // 执行查询方法        userMapper.saveUser(user);

        System.out.println(user);

        // 和spring整合后由spring管理        sqlSession.commit();

        sqlSession.close();

    }

}

测试结果与上一篇相同

四、总结

selectOne和selectList

动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。

namespace

mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Mybatis介绍 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache...
    day_Sunny阅读 2,718评论 0 6
  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,723评论 0 4
  • 1.1mybatis下载 mybaits 的代码由github.com 管理,地址:https://github....
    暖熊熊阅读 883评论 0 5
  • 天҉҉҈气҉҉҈太҉҉҈热,文҉҉҈字҉҉҈都҉҉҈出҉҉҈汗҉҉҈了҉҉҈ 热҉҉҈疯҉҉҈了,全҉҉҈身҉҉҈...
    我也是最懒啦阅读 193评论 0 0
  • 本周可谓处于 “近乎中暑”的状态。炎热的天气令人些许烦躁,当然还是个人修养欠缺吧。坐得令人后背疼痛的排练以及去外地...
    梁梦婷阅读 246评论 0 1