zoukankan      html  css  js  c++  java
  • Mybatis学习笔记(三) —— DAO开发方法

    一、SqlSession的使用范围

      SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。

      SqlSession通过SqlSessionFactory创建。

      SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。

    1.1 SqlSessionFactoryBuilder

      SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory创建的。所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量

    1.2 SqlSessionFactory

           SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。

    1.3 SqlSession

           SqlSession是一个面向用户的接口,sqlSession中定义了数据库操作方法。

           每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。

      打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。如下:

    SqlSession session = sqlSessionFactory.openSession();
    try {
         // do work
    } finally {
        session.close();
    }

    二、原始Dao开发方法(了解)

           原始Dao开发方法需要程序员编写Dao接口和Dao实现类。

    2.1 映射文件

    <?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="test">
    
        <!-- 根据id查询用户 -->
        <select id="queryUserById" parameterType="int"
            resultType="cn.itcast.mybatis.pojo.User">
            select * from user where id = #{id}
        </select>
    
        <!-- 根据username模糊查询用户 -->
        <select id="queryUserByUsername" parameterType="string"
            resultType="cn.itcast.mybatis.pojo.User">
            select * from user where username like '%${value}%'
        </select>
    
        <!-- 保存用户 -->
        <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User">
            <selectKey keyProperty="id" keyColumn="id" order="AFTER"
                resultType="int">
                SELECT LAST_INSERT_ID()
            </selectKey>
            insert into user(username,birthday,sex,address)
            values(#{username},#{birthday},#{sex},#{address})
        </insert>
    
    </mapper>

    2.2 DAO接口

    public interface UserDao {
        /**
         * 根据id查询用户
         * 
         * @param id
         * @return
         */
        User queryUserById(int id);
    
        /**
         * 根据用户名模糊查询用户
         * 
         * @param username
         * @return
         */
        List<User> queryUserByUsername(String username);
    
        /**
         * 保存用户
         * 
         * @param user
         */
        void saveUser(User user);
    }

    2.3 DAO实现类

    public class UserDaoImpl implements UserDao {
        private SqlSessionFactory sqlSessionFactory;
    
        public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
            super();
            this.sqlSessionFactory = sqlSessionFactory;
        }
    
        @Override
        public User queryUserById(int id) {
            // 创建SqlSession
            SqlSession sqlSession = this.sqlSessionFactory.openSession();
            // 执行查询逻辑
            User user = sqlSession.selectOne("queryUserById", id);
            // 释放资源
            sqlSession.close();
    
            return user;
        }
    
        @Override
        public List<User> queryUserByUsername(String username) {
            // 创建SqlSession
            SqlSession sqlSession = this.sqlSessionFactory.openSession();
    
            // 执行查询逻辑
            List<User> list = sqlSession.selectList("queryUserByUsername", username);
            // 释放资源
            sqlSession.close();
            return list;
        }
    
        @Override
        public void saveUser(User user) {
            // 创建SqlSession
            SqlSession sqlSession = this.sqlSessionFactory.openSession();
    
            // 执行保存逻辑
            sqlSession.insert("saveUser", user);
            // 提交事务
            sqlSession.commit();
            // 释放资源
            sqlSession.close();
        }
    }

    2.4 DAO测试

    public class UserDaoTest {
        private SqlSessionFactory sqlSessionFactory;
    
        @Before
        public void init() throws Exception {
            // 创建SqlSessionFactoryBuilder
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            // 加载SqlMapConfig.xml配置文件
            InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
            // 创建SqlsessionFactory
            this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        }
    
        @Test
        public void testQueryUserById() {
            // 创建DAO
            UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);
            // 执行查询
            User user = userDao.queryUserById(1);
            System.out.println(user);
        }
    
        @Test
        public void testQueryUserByUsername() {
            // 创建DAO
    
            UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);
            // 执行查询
            List<User> list = userDao.queryUserByUsername("张");
            for (User user : list) {
                System.out.println(user);
            }
        }
    
        @Test
        public void testSaveUser() {
            // 创建DAO
            UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);
    
            // 创建保存对象
            User user = new User();
            user.setUsername("刘备");
            user.setBirthday(new Date());
            user.setSex("1");
            user.setAddress("蜀国");
            // 执行保存
            userDao.saveUser(user);
    
            System.out.println(user);
        }
    }

    2.5 存在的问题

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

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

    三、Mapper动态代理方式 (重点)

    3.1 开发规范

       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.2 Mapper.xml(映射文件)

           定义mapper映射文件UserMapper.xml

      将UserMapper.xml放在config下mapper目录下,效果如下:

        

      UserMapper.xml配置文件内容:

    <?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 -->
    <!-- 还有一个很重要的作用:使用动态代理开发DAO,namespace必须和Mapper接口路径一致 -->
    <mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
        <!-- 根据用户id查询用户 -->
        <!-- id必须和Mapper接口方法名一致 -->
        <!-- parameterType必须和接口方法参数类型一致 -->
        <!-- resultType必须和接口方法返回值类型一致 -->
        <select id="queryUserById" parameterType="int" resultType="cn.itcast.mybatis.pojo.User">
            SELECT * FROM `user` WHERE id = #{id}
        </select>
        
        <!-- 根据用户名模糊查询用户 -->
        <select id="queryUserByUsername" parameterType="string" resultType="cn.itcast.mybatis.pojo.User">
            SELECT * FROM `user` WHERE username LIKE '%${value}%'
        </select>
        
        <!-- 保存用户 -->
        <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User">
            <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>
    </mapper>

    3.3 UserMapper(接口文件)

    public interface UserMapper {
        /**
         * 根据用户id查询用户
         * @param id
         * @return
         */
        User queryUserById(int id);
        
        /**
         * 根据用户名模糊查询用户
         * @param username
         * @return
         */
        List<User> queryUserByUsername(String username);
        
        /**
         * 保存用户
         * @param user
         */
        void saveUser(User user);
    }

    3.4 加载UserMapper.xml文件

      修改SqlMapConfig.xml文件,添加以下所示的内容:

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

    3.5 测试

    public class UserMapperTest {
        private SqlSessionFactory sqlSessionFactory;
        
        @Before
        public void init() throws Exception{
            // 创建SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            // 加载SqlMapConfig.xml配置文件
            InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
            // 创建sqlSessionFactory
            sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        }
        
        @Test
        public void testQueryUserById() throws Exception {
            // 获取sqlSession,和spring整合后由spring管理
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 从sqlSession中获取Mapper接口的代理对象
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            // 执行查询方法
            User user = userMapper.queryUserById(32);
            System.out.println(user);
            
            // 和spring整合后由spring管理
            sqlSession.close();
        }
        
        @Test
        public void testQueryUserByUsername() throws Exception {
            // 获取sqlSession,和spring整合后由spring管理
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 从sqlSession中获取Mapper接口的代理对象
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            // 执行查询方法
            List<User> list = userMapper.queryUserByUsername("王");
            for (User user : list) {
                System.out.println(user);
            }
            // 和spring整合后由spring管理
            sqlSession.close();
        }
        
        @Test
        public void testSaveUser() throws Exception {
            // 获取sqlSession,和spring整合后由spring管理
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 从sqlSession中获取Mapper接口的代理对象
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            // 创建保存对象
            User user = new User();
            user.setUsername("张飞");
            user.setAddress("蜀国");
            user.setSex("男");
            user.setBirthday(new Date());
            
            // 执行保存方法
            userMapper.saveUser(user);
            
            // 和spring整合后由spring管理
            sqlSession.commit();
            sqlSession.close();
        }
    }
  • 相关阅读:
    webform 下使用autofac
    AutoFac (控制反转IOC 与依赖注入DI)
    AutoFac使用方法总结:Part I
    Asp.net三种事务处理
    这二十个问题,可能是你技术人生中已经或即将遭遇的痛点,怎么解?
    已经过事务处理的 MSMQ 绑定(转载)
    实践.Net Core在Linux环境下的第一个Hello World
    Linux新手扫盲(转载)
    Redis 数据类型及其特点
    观察者模式深入实践
  • 原文地址:https://www.cnblogs.com/yft-javaNotes/p/10195799.html
Copyright © 2011-2022 走看看