Mybatis框架(7) —— 连接池与事务机制

连接池

  • 连接池是用于存储连接的容器
    • 容器必须是一个线程安全的集合对象,并且具有队列的特性:先进先出。

MyBatis连接池

  • 我们在前面的WEB课程中也学习过类似的连接池技术,而在Mybatis中也有连接池技术,但是它采用的是自
    己的连接池技术。
  • 在Mybatis中我们将它的数据源dataSource分为以下几类:
    • UNPOOLED采用传统的获取连接的方式
    • POOLED采用传统的 javax.sql.DataSource规范中的连接池
    • JNDI采用服务器提供的 JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。
      在这里插入图片描述

UNPLLED

执行语句,控制台显示结果

在这里插入图片描述

底层代码

  • 虽然 UNPOOLED 并没有使用池的思想,但是 MyBatis框架依然定义了 java.sql.DataSource接口 的实现类 UnpooledDataSource 来表示 UNPOOLED类型 的数据源。
    在这里插入图片描述
    在这里插入图片描述

POOLED

执行语句,控制台显示结果

在这里插入图片描述

底层代码

  • MyBatis框架定义了 java.sql.DataSource接口 的是实现类 DataSource 来表示 POOLED类型 的数据源。
    在这里插入图片描述

MyBatis连接池的配置

  • 在 Mybatis 的 SqlMapConfig.xml配置文件 中,通过 <dataSource type=“pooled”> 来实
    现 Mybatis 中连接池的配置。
<environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <!-- MyBatis连接池的配置 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

Mybatis连接池的存取

  • MyBatis 通过工厂模式来创建 DataSource连接池对象,MyBatis 定义了抽象的工厂接
    口:org.apache.ibatis.datasource.DataSourceFactory,通过其 getDataSource()方法 返回
    DataSource连接池对象。
  • 当我们需要创建 SqlSession对象 并需要执行 SQL语句 时,这时候 MyBatis 才会去调用 dataSource对象
    来创建 connection数据库连接对象。也就是说,Connection对象的创建一直延迟到执行SQL语句
    的时候
  • 数据库连接是我们最为宝贵的资源,只有在要用到的时候,才去获取并打开连接,当我们用完了就再
    立即将数据库连接归还到连接池中。

事务控制

  • 在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法 就可以调整。Mybatis框架 对 JDBC 进行了封装,所以 Mybatis框架 的事务控制方式,本身也是用 JDBC 的在·
    setAutoCommit()方法 来设置事务提交方式的

MyBatis事务控制

  • Mybatis中事务的提交方式,本质上就是调用JDBC的setAutoCommit()来实现事务控制。
  • 我们运行之前所写的代码:
public class UserTest {

    /* 成员变量 */
    private InputStream inputStream;
    private SqlSession session;
    private UserDao dao;

    /* 初始化操作 */
    @Before
    public void init() throws IOException {
        /* 加载 MyBatis配置文件 */
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        /* 获取 工厂类 */
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        /* 获取 产品类 */
        session = factory.openSession();
        /* 获取 代理对象 */
        dao = session.getMapper(UserDao.class);
    }

    /* 销毁操作 */
    @After
    public void destroy() throws IOException {
        session.close();
        inputStream.close();
    }


    /** 添加用户 */
    @Test
    public void test01(){
        dao.add( new User(100,"ADD",new Date(),"男","UserDao") );
        session.commit();
    }

    /** 更新用户 */
    @Test
    public void test02(){
        dao.update( new User(100,"UPDATE",new Date(),"男","UserDao") );
        session.commit();
    }

    /** 删除用户 */
    @Test
    public void test03(){
        dao.delete(100);
        session.commit();
    }


}

  • 控制台输出结果
    • 它显示了 Connection数据库连接对象 的整个变化过程
      在这里插入图片描述

MyBatis自动提交事务的设置

  • 通过上面的研究和分析,现在我们一起思考,为什么 CUD过程 中必须使用 sqlSession.commit()提交事
    务?
    • 主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法,这样我们
      就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法 实现事务提
      交。
    • 我们在通过 SqlSession工厂类 生产 SqlSession类 时,可以传递布尔值 true 来设置 自动提交事务。

在这里插入图片描述

MyBatis动态SQL语句的编写

if 标签

  • <if>标签 的 test属性 中写的是对象的属性名,如果是包装类的对象要使用OGNL表达式的写法。
    • 另外要注意where 1=1 的作用~!

持久层接口

/** 根据用户信息,查询用户列表 */
List<User> findByUser1(User user);

映射配置文件

<!-- SELECT * FROM user WHERE 1 = 1 AND username LIKE #{username} AND address LIKE #{address} -->
<select id="findByUser1" resultType="user" parameterType="user">

    /* SQL语句 */
    SELECT * FROM user WHERE 1 = 1

    /* 动态SQL语句 */
    <if test="username!=null and username!='' ">
        AND username LIKE #{username}
    </if>
    <if test="address!=null ">
        AND address LIKE #{address}
    </if>

</select>

测试类

@Test
public void test01(){
    for (User user : dao.findByUser1(new User("老王","北京"))) {
        System.out.println(user);
    }
}

where 标签

  • 为了简化上面where 1=1的条件拼装,我们采用<where>标签来简化开发。

持久层接口

/** 根据用户信息,查询用户 */
List<User> findByUser2(User user);

映射配置文件

<!-- 设置SQL语句 -->
<sql id="select">
    SELECT * FROM user
</sql>

<!-- SELECT * FROM user WHERE username LIKE #{username} AND address LIKE #{address} -->
<select id="findByUser2" resultType="user" parameterType="user">

    /* 使用设置的 SQL语句 */
    <include refid="select"></include>

    /* 动态SQL语句 */
    <where>
        <if test="username!=null and username!='' ">
            AND username LIKE #{username}
        </if>
        <if test="address!=null ">
            AND address LIKE #{address}
        </if>
    </where>

</select>

测试类

@Test
public void test02(){
    for (User user : dao.findByUser2(new User("老王","北京"))) {
        System.out.println(user);
    }
}

foreach 标签

QueryVo类

  • 封装List集合,存储要查询的ID
public class QueryVo implements Serializable {

    private List<Integer> ids;
    
    public List<Integer> getIds() {
        return ids;
    }
    
    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
}

持久层接口

/** 在ID范围,查询用户 */
List<User> findByIDs(QueryVo queryVo);

映射配置文件

  • SQL语句:
    • select 字段 from user where id in (?)
  • <foreach>标签 用于遍历集合,它的属性:
    • collection属性:代表要遍历的集合元素,注意编写时不要写#{}
    • open属性:代表语句的开始部分
    • close属性:代表结束部分
    • item属性:代表遍历集合的每个元素
    • sperator属性:代表分隔符
<!-- 设置SQL语句 -->
<sql id="select">
    SELECT * FROM user
</sql>

<!-- 在ID范围,查询用户 -->
<select id="findByIDs" resultType="user" parameterType="queryVo" >

    /* 使用设置的 SQL语句 */
    <include refid="select"></include>

    /* 动态SQL语句 */
    <where>
        <if test="list!=null and list.size()>0 ">
            <foreach collection="list" open=" id IN (" close=")" item="item" separator=",">
                #{item}
            </foreach>
        </if>
    </where>


</select>

测试类

@Test
public void test03(){
    List<Integer> list = new ArrayList<Integer>();
    Collections.addAll(list,41,42,43,46);
    for (User user : dao.findByIDs(new QueryVo(list))) {
        System.out.println(user);
    }
}
发布了68 篇原创文章 · 获赞 2 · 访问量 1917

猜你喜欢

转载自blog.csdn.net/qq_40981851/article/details/104191882