zoukankan      html  css  js  c++  java
  • 深入浅出Mybatis(五)mapper代理方法使用

    一、前言

          在前面分享了Mybatis的一些增删改查的操作过程,在接下来的过程中呢,可以说是涉及到一些框架的知识了,继续学习使用mapper代理方法。

    从原始三层的架构到Mapper代理

          下面这张图是最原始的三层架构的图,分成了UBD三个层,不同的层处理不同的事务。可以看出,当B和D之间的接触比较多的时候会对数据库造成很大的压力,数据库就会有多次的开闭。

     针对以上的问题,我们做了如下的改变,就在BD两层之间添加了IDAL一个接口层,这样B层对D层的所有的交互都处理在IDAL层上,D层通过实现这个接口,就可以减少对D层的访问线程数目。达到了一个解耦的效果。但是还是不能避免我们的D层要写好固定的sql语句,即硬编码。D层的结构就会很固定,不灵活。

     

    接下来就是我们通过使用Mybatis的框架把所有的sql语句写到Mapper.xml文件中,然后在全局配置文件中映射。Mapper.java通过一定的规范来提供方法。而且在SqlMapConfig.xml中配置数据库连接池,就减少了数据库的开闭,提高了数据库使用的效率。

    实现原理     

    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(内容同Users.xml),需要修改namespace的值为 UserMapper接口路径。将UserMapper.xml放在classpath 下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">
    <mapper namespace="com.dtt.mybatis.mapper.UserMapper"><!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 -->
        <!-- id:statement的id 或者叫做sql的id-->
        <!-- parameterType:声明输入参数的类型 -->
        <!-- resultType:声明输出结果的类型,应该填写pojo的全路径 -->
        <!-- #{}:输入参数的占位符,相当于jdbc的? -->
        <!-- 根据id获取用户信息 -->
        <select id="findUserById" parameterType="int"
                resultType="com.dtt.mybatis.pojo.User" >
            select *  from user where id = #{id}
        </select>
        <!-- 根据用户名,查询用户列表,支持模糊查询 -->
        <select id="findUserByUsername" parameterType="java.lang.String"
                resultType="com.dtt.mybatis.pojo.User">
            select *  from user where username like '%${value}%'
        </select>
        <insert id="insertUser" parameterType="com.dtt.mybatis.pojo.User">
            <!-- 将插入数据的主键返回,返回到user对象中。 select LAST_INSERT_ID():得到刚insert进行的记录的主键,只适用于自增主键
                keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性。 order:select LAST_INSERT_ID()执行顺序,相对insert语句来说他的执行顺序
                resultType:指定select LAST_INSERT_ID()的返回数据的类型 -->
            <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
    
                select LAST_INSERT_ID()
            </selectKey>
            insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
        </insert>
        <delete id="delUserById" parameterType="int">
            delete from user where id=#{id}
        </delete>
        <update id="updateUserById" parameterType="com.dtt.mybatis.pojo.User">
            update user set username=#{username} where id=#{id}
        </update>
    </mapper>
    

    Mapper.java(接口文件)

          代码如下:

    package com.dtt.mybatis.mapper;
    
    import com.dtt.mybatis.pojo.User;
    
    import java.util.List;
    
    /**
     * 用户管理mapper
     */public interface UserMapper {
         //根据用户id查询用户信息
    public User findUserById(int id) throws Exception;
    //查询用户列表
    public List<User> findUserByUsername(String username) throws Exception;
    //添加用户信息
    public void insertUser(User user)throws Exception; }
    

     接口定义有如下特点:

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

          2、 Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同

          3、 Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同

    SqlMapConfig.xml加载映射文件

          修改SqlMapConfig.xml文件:

    <!-- 加载映射文件 -->
        <mappers>
            <mapper resource="mapper/UserMapper.xml"/>
        </mappers>
    

     测试代码如下:

    package com.dtt.mybatis.test;
    
    import com.dtt.mybatis.pojo.User;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Date;
    import java.util.List;
    
    
    public class UserTest {
        //会话工厂
        private SqlSessionFactory sqlSessionFactory;
    
        // Before在开始测试之前加载的方法,主要是创建会话工厂
        @Before
        public void createSqlSessionFactory() throws IOException {
            //配置文件
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 使用SqlSessionFactoryBuilder从xml配置文件中创建SqlSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }
    
        @Test
        public void testFindUserById() {
            //数据会话实例
            SqlSession sqlSession = null;
            try {
                /* 创建数据库会话实例 */
                sqlSession = sqlSessionFactory.openSession();
                // 查询单个记录,根据用户id查询用户信息
                User user = sqlSession.selectOne("test.findUserById", 10);
                // 输出用户信息
                System.out.println(user);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
    
    
        }
        // 根据用户名称模糊查询用户信息
        @Test
        public void testFindUserByUsername() {
            // 数据库会话实例
            SqlSession sqlSession = null;
            try {
                // 创建数据库会话实例
                sqlSession = sqlSessionFactory.openSession();
                // 查询单个记录,根据用户id查询用户信息
                List<User> list = sqlSession.selectList("test.findUserByUsername", "小");
                System.out.println(list.size());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
        }
        @Test
        public void testInsertUser(){
    
            //数据库会话
             SqlSession sqlSession=null;
             try {
                 sqlSession=  sqlSessionFactory.openSession();
                 //添加数据信息
                 User user = new User();
                 user.setSex("2");
                 user.setAddress("sadfsafsafs");
                 user.setBirthday(new Date());
                 user.setUsername("婷婷");
                 sqlSession.insert("test.insertUser", user);
                 sqlSession.commit();
                 System.out.println("添加成功)");
                 System.out.println(user.getId());
             }catch( Exception e){
                 e.printStackTrace();
             }
            finally{
                 if(sqlSession!=null){
                     sqlSession.close();
                 }
    
            }
        }
    // 根据id删除用户
    @Test
    public void testDelete() {
            // 数据库会话实例
        SqlSession sqlSession = null;
        try {
            // 创建数据库会话实例
            sqlSession = sqlSessionFactory.openSession();
            // 删除用户
            sqlSession.delete("test.delUserById",55);
            // 提交事务
            sqlSession.commit();
            System.out.println("删除成功");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
        }
         @Test
        public void testUpateUser(){
             // 数据库会话实例
             SqlSession sqlSession = null;
             try {
                 // 创建数据库会话实例
                 sqlSession = sqlSessionFactory.openSession();
                 // 添加用户
                User user =new User ();
                user.setId(20);
                user.setSex("1");
                user.setAddress("浙江");
                user.setBirthday(new Date());
                user.setUsername("凤凰女");
                sqlSession.update("test.updateUserById",user);
                sqlSession.commit();
                 System.out.println(user.getId());
                 System.out.println(user.getUsername());
             } catch (Exception e) {
                 e.printStackTrace();
             } finally {
                 if (sqlSession != null) {
                     sqlSession.close();
                 }
             }
    
    
         }
    }
    

    小结

          这里的mapper代理方法其实就是加入了一个接口层,这个接口的方法命名有要和id相同,初始参数要和parameterType类型相同,返回值要和resultType相同,这些都是为了我们映射规定的规范。使得更加的灵活。

  • 相关阅读:
    转 无障碍阅读 role aria-*
    (转)edm注意事项
    Spring IOC机制之使用注解配置bean
    Spring IOC机制使用SpEL
    使用Spring IOC容器引用外部属性文件
    如何将属性文件中的值保存到类中
    基于XML的类的属性的装配
    Java——事务
    Eclipse中使用Spring IOC容器的具体方法
    Java之批处理的实现
  • 原文地址:https://www.cnblogs.com/mtime2004/p/9893031.html
Copyright © 2011-2022 走看看