侧边栏壁纸
博主头像
coydone博主等级

记录学习,分享生活的个人站点

  • 累计撰写 306 篇文章
  • 累计创建 51 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

事务和动态SQL

coydone
2022-03-08 / 0 评论 / 0 点赞 / 366 阅读 / 5,482 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-04-10,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Mybatis的事务控制

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

之前的CUD(增删改) 操作过程中,我们都要手动进行事务的提交,原因是setAutoCommit()方法,在执行时它的值被设置为false了,所以我们在CUD操作中,必须通过sqlSession.commit()方法来执行提交操作。

设置自动提交事务

为什么CUD过程中必须使用sqlSession.commit()提交事务?

主要原因就是在连接池中取出的连接,都会将调用connection.setAutoCommit(false)方法,这样我们就必须使用 sqlSession.commit()方法,相当于使用了JDBC中的 connection.commit()方法实现事务提交。

设置自动提交事务代码

//4.创建 SqlSession 对象 false改成true就会自动执行session.commit自动提交
//SqlSession session = sqlSessionFactory.openSession(false);
session = factory.openSession(true);

Mybatis的动态SQL语句

Mybatis的映射文件中,前面我们的SQL都是比较简单的,有些时候业务逻辑复杂时,我们的SQL是动态变化的,此时在前面的学习中我们的SQL就不能满足要求了。

if标签

我们根据实体类的不同取值,使用不同的SQL语句来进行查询。比如在id如果不为空时可以根据id查询,如果username不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

持久层Dao接口

/**
* 根据传入参数条件
* @param user 查询的条件:有可能有用户名,有可能有性别,也有可能有地址,还有可能是都有
* @return 实体的list集合
*/
List<User> findUserByCondition(User user);

持久层Dao映射配置

<!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
<resultMap id="userMap" type="uSeR">
    <!-- 主键字段的对应 -->
    <id property="userId" column="id"></id>
    <!--非主键字段的对应-->
    <result property="userName" column="username"></result>
    <result property="userAddress" column="address"></result>
    <result property="userSex" column="sex"></result>
    <result property="userBirthday" column="birthday"></result>
</resultMap>
<!-- 根据条件查询-->
<select id="findUserByCondition" resultMap="userMap" parameterType="user">
    select * from user where 1=1
    <if test="userName != null">
        and username = #{userName}
    </if>
    <if test="userSex != null">
        and sex = #{userSex}
    </if>
</select>

where标签

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

<select id="findUserByCondition" resultMap="userMap" parameterType="user">
    select * from user
    <where>
        <if test="userName != null">
            and username = #{userName}
        </if>
        <if test="userSex != null">
            and sex = #{userSex}
        </if>
    </where>
</select>

trim

自定义字符串截取(用的不多,根据需求选择)。

 <!--public List<Employee> getEmpsByConditionTrim(Employee employee);  -->
<select id="getEmpsByConditionTrim" resultType="com.coydone.mybatis.bean.Employee">
    select * from tbl_employee
    <!-- 后面多出的and或者or where标签不能解决 
   prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
     prefix给拼串后的整个字符串加一个前缀 
   prefixOverrides="":
     前缀覆盖: 去掉整个字符串前面多余的字符
   suffix="":后缀
     suffix给拼串后的整个字符串加一个后缀 
   suffixOverrides=""
     后缀覆盖:去掉整个字符串后面多余的字符	
   -->
    <!-- 自定义字符串的截取规则 -->
    <trim prefix="where" suffixOverrides="and">
        <if test="id!=null">
            id=#{id} and
        </if>
        <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
            last_name like #{lastName} and
        </if>
        <if test="email!=null and email.trim()!=&quot;&quot;">
            email=#{email} and
        </if> 
        <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
        <if test="gender==0 or gender==1">
            gender=#{gender}
        </if>
    </trim>
</select>

choose分支选择

<!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->
<select id="getEmpsByConditionChoose" resultType="com.coydone.mybatis.bean.Employee">
    select * from tbl_employee 
    <where>
        <!-- 如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个!! -->
        <choose>
            <when test="id!=null">
                id=#{id}
            </when>
            <when test="lastName!=null">
                last_name like #{lastName}
            </when>
            <when test="email!=null">
                email = #{email}
            </when>
            <otherwise>
                gender = 0
            </otherwise>
        </choose>
    </where>
</select>

foreach标签

传入多个id查询用户信息,用下边两个 SQL实现:

SELECT * FROM USERS WHERE id IN (41,42,43)这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。

在 QueryVo 中加入一个 List 集合用于封装参数。

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

持久层 Dao 接口

//根据 id 集合查询用户
List<User> findInIds(QueryVo vo);

持久层 Dao 映射配置

<!-- 查询所有用户在 id 的集合之中 -->
<select id="findInIds" resultType="user" parameterType="queryvo">
<!-- select * from user where id in (1,2,3,4,5); --> 
	select * from user
    <where>
        <if test="ids != null and ids.size() > 0">
            <foreach collection="ids" open="id in ( " close=")" item="uid"
            separator=",">
	            #{uid}
            </foreach>
        </if>
    </where>
</select>

SQL 语句:select 字段 from user where id in (?)

foreach标签用于遍历集合,它的属性:

  • collection:代表要遍历的集合元素,注意编写时不要写#{}

  • open:代表语句的开始部分。

  • close:代表结束部分。

  • item:代表遍历集合的每个元素,生成的变量名。

  • sperator:代表分隔符。

编写测试方法

@Test
public void testFindInIds() {
    QueryVo vo = new QueryVo();
    List<Integer> ids = new ArrayList<Integer>();
    ids.add(41);
    ids.add(42);
    ids.add(43);
    vo.setIds(ids);
    //6.执行操作
    List<User> users = userDao.findInIds(vo);
    for(User user : users) {
        System.out.println(user);
    }
}

简化编写的SQL片段

定义代码片段

<sql id="defaultUser">
    select * from user
</sql>

引用代码片段

<!-- 根据queryvo中的Id集合实现查询用户列表 -->
<select id="findUserInIds" resultMap="userMap" parameterType="queryvo">
    <include refid="defaultUser"></include>
    <where>
        <if test="ids != null and ids.size()>0">
            <foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
                #{uid}
            </foreach>
        </if>
    </where>
</select>
0

评论区