不灭的焱

革命尚未成功,同志仍须努力下载JDK17

作者:php-note.com  发布于:2022-05-14 17:01  分类:Java框架/系统  编辑

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

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

  1. UI(表现层):主要是指与用户交互的界面。用于接收用户输入的数据和显示处理后用户需要的数据。
  2. BLL(业务逻辑层):UI层和DAL层之间的桥梁。实现业务逻辑。业务逻辑具体包含:验证、计算、业务规则等等。
  3. DAL(数据访问层):与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交给业务层,同时将业务层处理的数据保存到数据库。(当然这些操作都是基于UI层的。用户的需求反映给界面(UI),UI反映给BLL,BLL反映给DAL,DAL进行数据的操作,操作后再一一返回,直到将用户所需数据反馈给用户)

                                            

针对以上的问题,我们做了如下的改变,就在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的类型相同

三、操作

3.1 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="cn.itcast.mybatis.mapper.UserMapper">
<!-- 根据id获取用户信息 -->
    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
        select * from user where id = #{id}
    </select>
<!-- 自定义条件查询用户列表 -->
    <select id="findUserByUsername" parameterType="java.lang.String" 
            resultType="cn.itcast.mybatis.po.User">
       select * from user where username like '%${value}%' 
    </select>
<!-- 添加用户 -->
    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
    <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>

</mapper>

3.2 Mapper.java(接口文件)

代码如下:

/**
 * 用户管理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的类型相同

3.3 SqlMapConfig.xml加载映射文件

修改SqlMapConfig.xml文件:

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

3.4 测试

测试代码如下:

Public class UserMapperTest extends TestCase {

    private SqlSessionFactory sqlSessionFactory;

    protected void setUp() throws Exception {
        //mybatis配置文件
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //使用SqlSessionFactoryBuilder创建sessionFactory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }


    Public void testFindUserById() throws Exception {
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获取mapper接口的代理对象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //调用代理对象方法
        User user = userMapper.findUserById(1);
        System.out.println(user);
        //关闭session
        session.close();

    }
	
    @Test
    public void testFindUserByUsername() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = userMapper.findUserByUsername("张");
        System.out.println(list.size());

    }
	
	Public void testInsertUser() throws Exception {
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        
		//获取mapper接口的代理对象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        
		//要添加的数据
        User user = new User();
        user.setUsername("张三");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("北京市");
        
		//通过mapper接口添加用户
        userMapper.insertUser(user);
        
		//提交
        session.commit();
        
		//关闭session
        session.close();
    }
}

四、小结

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

 

 

摘自:https://blog.csdn.net/kisscatforever/article/details/60880817