• mybatis从入门到精通(五) sqlSession API的使用


    mybatis从入门到精通(五) sqlSession API的使用

     一丶简介

       SqlSession类似于mybatis对外的接口层, 它几乎囊括了所有对外的api, 因此, 学习SqlSession的使用方法对于了解mybatis还是有必要的.

     对应官方文档

    二丶配置SqlSession的环境<environment/>

       <environment/> 主要包括了两种配置, 事务管理和数据源. 这里的配置仅仅是用于学习, 实际应用一般是将事务交由Spring容器管理, 数据源一般选用成熟的数据库连接池, 如druid, HikariCP

        <environments default="development">
            <environment id="development" >
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>

    三丶使用配置构建对应的SqlSessionFactory

            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    四丶使用SqlSessionFactory获取SqlSession

      在获取SqlSession实例之前, 需要考虑以下3件事:

        事务处理:我需要在 session 使用事务或者使用自动提交功能(auto-commit)吗?(通常意味着很多数据库和/或 JDBC 驱动没有事务)
        连接:我需要依赖 MyBatis 获得来自数据源的配置吗?还是使用自己提供的配置?
        执行语句:我需要 MyBatis 复用预处理语句和/或批量更新语句(包括插入和删除)吗?

      4.1) 默认方法

        @Test
        public void sqlSessionTest(){
            // openSession() 会开启一个事务, 它不会自动提交
            // 会从当前环境配置的Datasource实例中获取Connection
            // 事务隔离级别使用jdbc或数据源默认的配置
            // 不会复用预处理语句, 每次都是新建一个处理语句
            try(SqlSession sqlSession=this.sqlSessionFactory.openSession();){
                UserMapper mapper=sqlSession.getMapper(UserMapper.class);
                User user=mapper.selectUser(1);
                sqlSession.commit();
                Assert.assertTrue(user.getUserId() == 1);
            }
        }

      4.2) 批量执行(自定义)

        /*
        SqlSession openSession() //默认开启事务, 不自动提交
        SqlSession openSession(boolean autoCommit)  // 可设置是否自定提交
        SqlSession openSession(Connection connection)  // 需要使用自定义的connection, 传递参数即可, 注意并未覆写同时设置 Connection 和 autoCommit 两者的方法,因为 MyBatis 会使用正在使用中的、设置了 Connection 的环境
        SqlSession openSession(TransactionIsolationLevel level) // 事务隔离级别 
        SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level)
        SqlSession openSession(ExecutorType execType)
        SqlSession openSession(ExecutorType execType, boolean autoCommit)
        SqlSession openSession(ExecutorType execType, Connection connection)
        Configuration getConfiguration();
        
        ExecutorType.SIMPLE:这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。
        ExecutorType.REUSE:这个执行器类型会复用预处理语句。
        ExecutorType.BATCH:这个执行器会批量执行所有更新语句,如果 SELECT 在它们中间执行,必要时请把它们区分开来以保证行为的易读性。
         */
        @Test
        public void sqlSessionTest2(){
            SqlSession sqlSession=null;
            try{
                /*
                批量执行 
                DEBUG [main] - ==>  Preparing: insert into user(user_id, user_name, age, country) values (?, ?, ?, ?) 
                DEBUG [main] - ==> Parameters: 11(Integer), ttxxxxxx(String), 11(Integer), null
                DEBUG [main] - ==> Parameters: 12(Integer), ttxxxxx12(String), 12(Integer), null
                 */
                sqlSession=sqlSessionFactory.openSession(ExecutorType.BATCH);
                UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
                
                
                User user=new User();
                user.setUserId(11);
                user.setAge(11);
                user.setUserName("ttxxxxxx");
                userMapper.insertUser(user);
                
                
                user.setUserId(12);
                user.setAge(12);
                user.setUserName("ttxxxxx12");
                userMapper.insertUser(user);
                
                sqlSession.commit();
                
            }catch (Exception e){
                e.printStackTrace();
                if(sqlSession!=null){
                    sqlSession.rollback();
                }
            }finally {
                if(sqlSession!=null){
                    sqlSession.close();
                }
            }
        }

      4.3) 使用statement指定对应的方法,执行对应的sql  

      该方法更加原始,更接近底层. 之前使用sqlSession.getMapper(UserMapper.class)获取对应的mapper实例, 不过是使用动态代理, 生成的代理类, 里面的方法也是使用stement指定对应的方法, 执行对应的sql

        /*
        sqlSession执行语句的的方法
        注意, statement是mapper对应的类名+方法名, 用于指定对应的sql语句
        
        <T> T selectOne(String statement, Object parameter)
        <E> List<E> selectList(String statement, Object parameter)
        <T> Cursor<T> selectCursor(String statement, Object parameter)  //返回一个游标, 可延迟获取数据
        <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
        int insert(String statement, Object parameter)
        int update(String statement, Object parameter)
        int delete(String statement, Object parameter)
         */
        @Test
        public void execSqlTest(){
            try(SqlSession sqlSession=this.sqlSessionFactory.openSession()){
                
                Cursor<User> userCursor=sqlSession.selectCursor("com.ttx.example.mapper.UserMapper.selectUser", 1); // statement 是 类名+方法名
                
                Iterator<User> iter=userCursor.iterator();
                while (iter.hasNext()){
                    User user=iter.next();
                    System.out.println(user.getUserId()+" : "+ user.getUserName());
                }
            }
        }

      4.4) @SqlProvider 在java代码中编写sql

          UserSqlProvider.java

    public static String buildSelectUserById(){
            return new SQL(){{
                SELECT("*");
                FROM("user");
                WHERE("user_id = #{userId}");
                ORDER_BY("user_id");
            }}.toString();
        }

      UserSqlProviderMapper.java

        @ResultMap("UserMap")
        @SelectProvider(type = UserSqlProvider.class, method = "buildSelectUserById")
        User selectUserById(@Param("userId") int userId);

      UserSqlProviderMapper.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">
    <mapper namespace="com.ttx.example.mapper.UserSqlProviderMapper">
        
        <!-- resultMap, 结果映射 -->
        <resultMap id="UserMap" type="com.ttx.example.entity.User">
            <constructor></constructor>  <!-- 用于引用构造参数, 可以省略掉 -->
            <id column="user_id" property="userId"/>  <!-- id 元素表示的结果将是对象的标识属性 -->
            <result column="user_name" property="userName"/>
            <result column="age" property="age"/>
            <result column="country" property="country"/>
        </resultMap>
    
    </mapper>

      测试代码

        // 注解 @SelectProvider
        @Test
        public void sqlProviderTest(){
            
            try(SqlSession sqlSession=this.sqlSessionFactory.openSession()){
                UserSqlProviderMapper mapper=sqlSession.getMapper(UserSqlProviderMapper.class);
                User user=mapper.selectUserById(1);
                
                Assert.assertTrue(user.getUserId()==1);
            }
            
        }
        

      注意事项, 使用SqlSession之后, 需要关闭连接, 上面中的代码使用了try(){}, 会自动关闭

      源码点此查看

    学习资料:

      官方文档

    人生没有彩排,每一天都是现场直播
  • 相关阅读:
    Mysql_常规操作
    三剑客
    Nginx_安全2
    shell_常规小脚本
    redis数据库持久化
    redis数据库操作
    keepalived高可用lvs集群
    ansible的roles角色
    keepalived高可用
    keepalived概念
  • 原文地址:https://www.cnblogs.com/timfruit/p/11391887.html
Copyright © 2020-2023  润新知