MyBatis_Day2_内置数据源、动态SQL、定制SQL片段、多表关联查询

内置数据源(连接池、事务管理器)

数据源

在 Mybatis 的 SqlMapConfig.xml 配置文件中,通过 <dataSource type="pooled">来实现 Mybatis 中连接池的配置。

别名对应的类:

  • POOLED:PooledDataSourceFactory ---> PooledDataSource

  • UNPOOLED:UnpooledDataSourceFactory ---> UnpooledDataSource

  • JNDI:JndiDataSourceFactory ---> JndiDataSource

POOLED

没有创建原生链接,是利用代理的方式生产链接,调用close方法时将链接归还到数据源,适用于企业级的Web应用,在面对一定并发量时,通常使用POOLED数据源优化数据库链接。

优点

性能提升:提供复用已创建的链接,避免了频繁创建和关闭链接的开销,在高并发的场景下,更快地响应请求。

资源优化:有效管理数据库连接资源,避免了资源的浪费

稳定性增强:因为减少了链接的创建和关闭,对象的错误和异常也相对减少,提高了系统的稳定性

UNPOOLED

创建原生链接,没有对连接池进行管理,调用close方法时直接关闭链接,适用于小型、低并发的应用场景。

优点

简单易用:配置和使用相对简单,不需要复杂的连接池管理设置

适合低并发场景:在并发量极低的情况下,不会因为连接池的管理带来额外的开销

独立运行:不依赖与连接池的机制,在某些特殊环境或需求下,可以更灵活地控制连接的行为。

JNDI(已淘汰)

数据源通过Java Naming and Directory Interface(JNDI)获取数据源,在企业级应用服务器环境中,经常会配置JNDI数据源,MyBatis可以通过配置直接使用这些已存在的数据源。

淘汰原因

复杂性:JNDI的配置和使用相对负载,需要在应用服务器中进行一系列的设置和管理,增加了开发和维护的难度。

灵活性受限:因为复杂性高,因此在部署在不同的环境或迁移应用时,JDNI的配置可能需要大量的调整和重新配置

与现代架构不匹配:随着微服务架构和云原生应用的兴起,更加轻量级和灵活的数据源管理方式更受欢迎。JDNI过于与特点应用服务器紧密耦合。

技术更新:越来越多新技术及框架不断涌现,提供了更简单、高效、灵活的数据源管理方案。

事务管理器

JDBC

默认的事务管理器,直接使用JDBC的连接来管理事务,使用原生的JDBC提交和回滚。适用于简单的应用场景。

Configuration中JDBC别名的全称:jdbcTransactionFactory

MyBatis的配置文件:

<!--采用JdbcTransaction事务管理器来管理事务-->
<transactionManager type="JDBC"></transactionManager>

test:

@Before
public void before() throws Exception {
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory sessionFactory = builder.build(Resources.getResourceAsReader("MyBatisConfig.xml"));
​
    /**
     * 设置是否自动提交事务:
     *  true:         自动提交事务,不经过事务管理器(因为JDBC连接默认就是自动提交)
     *  false(默认值): 手动提交事务,由于JDBC连接默认为自动提交,因此设置为false时将会使用事务管理器来回滚事务
     */
    session = sessionFactory.openSession(true);
    empDao = session.getMapper(EmpDao.class);
}
​
@After
public void after() throws Exception {
    session.close();
}
​
@Test
public void test1() throws Exception {
    empDao.delete(2);
​
    // 使用事务管理器的commit()方法来提交事务(必须要先设置为手动提交)
    session.commit();
​
    // 使用事务管理器的rollback()方法来回滚事务
//        session.rollback();
}

MANAGED

适用于应用服务器管理事务,在这种情况下,MyBatis会将事务管理委托给应用服务器

由于JDBC连接默认的策略是自动提交,因此采用MANAGED则不能回滚事务

Configuration中MANAGED别名的全称:ManagedTransactionFactory

MyBatis配置文件:

<!--采用ManagedTransaction事务管理器来管理事务-->
<transactionManager type="MANAGED"></transactionManager>

test:

@Before
public void before() throws Exception {
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory sessionFactory = builder.build(Resources.getResourceAsReader("MyBatisConfig.xml"));
​
    /**
     * 设置是否自动提交事务:
     *  true:         自动提交事务,不经过事务管理器(因为JDBC连接默认就是自动提交)
     *  false(默认值): 手动提交事务,在Managed模式下,即使设置了false最终经过事务管理器也无法回滚事务了
     */
    session = sessionFactory.openSession(true);
    empDao = session.getMapper(EmpDao.class);
}
​
​
@After
public void after() throws Exception {
    session.close();
}
​
@Test
public void test1() throws Exception {
    empDao.delete(2);
​
    // 执行ManagedTransaction的commit方法(空方法)
    session.commit();
​
    // 执行ManagedTransaction的rollback方法(空方法)
//        session.rollback();
}

动态SQL

if标签

 <select id="MyClassName" resultType="emp">
        select * from emp where 1=1
        <if test="id!=null">
            and id=#{id}
        </if>
        <if test="name!=null">
            and name=#{name}
        </if>
    </select>

where标签

会智能添加“where”并去除if标签中开头的“and”

<select id="findByIdAndName" resultType="emp">
    select * from emp
    <where>
        <if test="id!=null">
            and id=#{id}
        </if>
        <if test="name!=null">
            and name=#{name}
        </if>
    </where>
</select>

foreach标签

传递list集合时if语句中可以使用list或collection来取值

传递set集合时if语句中只能使用collection来取值

传递数组时if语句中只能使用array来取值

<select id="findByIds" resultType="emp">
    select * from emp
    <where>
        <!-- 使用list/collection/array获取集合的值 -->
        <if test="list!=null and collection.size>0">
            id in 
            <foreach collection="list" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </if>
    </where>
</select>

参数:

open:前缀

close:后缀

item:遍历出来的元素名称

separator:分割符

choose标签

只有当when标签都不成立时才会执行otherwise标签

<select id="findByEmp" resultType="emp">
    select * from emp
    <where>
        <choose>
            <when test="id!=null">
                and id=#{id}
            </when>
            <when test="name!=null">
                and name like #{name}
            </when>
            <otherwise>
                and 1!=1
            </otherwise>
        </choose>
    </where>
</select>

set标签

会智能添加“set”并去除if语句前后的“,”

<update id="update">
    update emp
    <set>
        <if test="name != null">
            name = #{name},
        </if>
        <if test="age != null">
            age = #{age},
        </if>
        <if test="addr != null">
            addr = #{addr},
        </if>
        <if test="salary != null">
            salary = #{salary},
        </if>
    </set>
    where id=#{id}
</update>

trim标签

与where标签类似,不过可以定制化去除/添加前后的关键字

<select id="findByIdOrName" resultType="emp">
    select * from emp
    <trim prefix="where" prefixOverrides="and|or">
        <if test="id!=null">
            or id = #{id}
        </if>
        <if test="name!=null">
            or name = #{name}
        </if>
    </trim>
</select>
​
​
<update id="update2" parameterType="Emp">
    update emp
    <trim prefix="set" suffixOverrides=",">
        <if test="name != null">
            name = #{name},
        </if>
        <if test="age != null">
            age = #{age},
        </if>
        <if test="addr != null">
            addr = #{addr},
        </if>
        <if test="salary != null">
            salary = #{salary},
        </if>
    </trim>
    where id=#{id}
</update>
​
​
<insert id="save" parameterType="Emp">
    insert into emp
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="id!=null">
            id,
        </if>
        <if test="name!=null">
            name,
        </if>
    </trim>
​
    values
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="id!=null">
            #{id},
        </if>
        <if test="name!=null">
            #{name},
        </if>
    </trim>
</insert>

参数:

属性说明
prefix给SQL语句拼接的前缀
suffix给SQL语句拼接的后缀
prefixOverrides去除的前缀
suffixOverrides去除的后缀

定制SQL片段

提前写好静态SQL片段(include标签中refid的value也可以是完整路径)

<sql id="findEmp">
    select * from emp
</sql>
​
<select id="findByIds" resultType="emp">
    <include refid="findEmp"></include>
    <where>
        <if test="collection!=null and collection.size>0">
            id in
            <foreach collection="collection" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </if>
    </where>
</select>

多表关联查询

一对一

手动映射

<mapper namespace="com.xxx.dao.EmpDao">
​
    //手动映射
    <resultMap id="empResultMap" type="emp">
        <id column="eId" property="id"></id>
        <result column="empName" property="name"></result>
        <result column="addr" property="addr"></result>
        <result column="salary" property="salary"></result>
        <result column="deptId" property="dept.id"></result>
        <result column="deptName" property="dept.name"></result>
        <result column="location" property="dept.location"></result>
    </resultMap>
    
    //sql语句
    <select id="findAll" resultMap="empResultMap">
        SELECT
        e.id eId,
        e.NAME empName,
        e.addr,
        e.salary,
        e.dept_id deptId,
        d.name deptName,
        d.location
    FROM
        emp e
        LEFT JOIN dept d ON e.dept_id = d.id
    </select>
</mapper>

关系映射:association标签

在使用关系映射时,即使查询出来的列明和实体类的属性名一致,也要手动映射

<resultMap id="empResultMap" type="emp">

	//手动映射
    <id column="eId" property="id"></id>
    <result column="empName" property="name"></result>
    <result column="addr" property="addr"></result>
    <result column="salary" property="salary"></result>
    
    //关系映射
    <association property="dept" javaType="com.dfbz.entity.Dept">
        <id column="deptId" property="id"></id>
        <result column="deptName" property="name"></result>
        <result column="location" property="location"></result>
    </association>
    
</resultMap>

参数:

property:对象中的属性

javaType:属性类型

一对多:collection标签

<mapper namespace="com.xxx.dao.DeptDao">

    <resultMap id="deptResultMap" type="dept">
    
    	//手动映射
        <id column="deptId" property="id"></id>
        <result column="deptName" property="name"></result>
        <result column="location" property="location"></result>

		//关系映射
        <collection property="empList" ofType="com.dfbz.entity.Emp">
            <id column="eId" property="id"></id>
            <result column="empName" property="name"></result>
            <result column="addr" property="addr"></result>
            <result column="salary" property="salary"></result>
        </collection>
        
    </resultMap>
    
    <select id="findAll" resultMap="deptResultMap">
        SELECT
            e.id eId,
            e.NAME empName,
            e.addr,
            e.salary,
            e.dept_id deptId,
            d.NAME deptName,
            d.location
        FROM
            emp e
            right JOIN dept d ON e.dept_id = d.id
    </select>
</mapper>

参数:

property:对象中的属性

ofType:集合中的泛型类型

多对多

主表在左,使用 left join

主表在右,使用 right join

<mapper namespace="com.dfbz.dao.UserDao">
    <resultMap id="userResultMap" type="user">

		//手动映射
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>

		//关系映射
        <collection property="roles" ofType="role">
            <id property="roleId" column="rid"></id>
            <result property="roleName" column="role_name"></result>
            <result property="roleDesc" column="role_desc"></result>
        </collection>
    </resultMap>
    
    <select id="findAll" resultMap="userResultMap">
    select
        u.*,
        r.id rid,
        r.role_name,
        r.role_desc
    
        from user u
        left join user_role ur on u.id=ur.uid
        left join role r on r.id=ur.rid
    </select>
</mapper>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值