MyBatis详解(4)--结合接口和XML使用MyBatis

需求缘起

第一小节我们用了纯 xml 的形式来使用MyBatis,第二节中我们使用了接口和注解(注解不能单独使用)相结合的形式来操作MyBatis,那有没有可能使用 xml 和 接口结合起来使用呢?答案是肯定的,而且这种用法会更加的灵活强大,使用纯xml的时候,当参数复杂且为多个的时候,使用xml方式很不方便,而且无法避免很多重复的代码;当使用接口和注解的相结合的时候又失去了灵活性(参考动态SQL那一小节);当使用xml和接口相结合的时候就可以完美解决这两者缺点,这一节我们就来学下 xml 结合接口的使用方式

本小节代码
mybatis-demo-article(4)

1.定义接口

使用第二节中的 UserMapper 接口,去掉其中的 sql 注解,另外添加第三节中用到的几个接口,结果如下

package com.mybatis.demo.mapper;

import com.mybatis.demo.model.UserInfo;

import java.util.List;

/**
 * @auther kklu
 * @date 2019/10/14 12:18
 * @describe
 */

public interface UserInfoMapper {

    //根据用户名和性别查询
    List<UserInfo> selectUserInfoByUsernameAndSex(UserInfo userInfo) throws Exception;
    
    //根据 id 修改 user_info 表数据
    void updateUserInfoById(UserInfo userInfo) throws Exception;

    //根据某一个条件查询
    List<UserInfo> selectUserInfoByChoose(UserInfo userInfo) throws Exception;

    //根据一组用户 id 查询用户
    List<UserInfo> selectUserByListId(UserInfoForm userInfoForm) throws Exception;
    
    //根据 id 查询 user_info 表数据
    UserInfo selectUserInfoById(int id) throws Exception;

    //查询 user_info 表所有数据
    List<UserInfo> selectUserInfoAll() throws Exception;

    //根据 id 查询 user_info 表数据
    List<UserInfo> selectLikeUserName(String username) throws Exception;

    //向 user_info 表插入一条数据
    void insertUserInfo(UserInfo userInfo) throws Exception;
    
    //根据 id 删除 user_info 表数据
    void deleteUserInfoById(int id) throws Exception;
    
}

2.注册接口

在配置文件 mybatis-config.xml mybatis-config.xml 中修改 标签中的 参数

   <mappers>
        <!--xxxMapper.java 接口文件的路径,注册单个接口的方式-->
        <!--<mapper class="com.mybatis.demo.mapper.UserInfoMapper"/>-->
        
        <!--注册多个接口的方式,该包名下所有的接口-->
        <package name="com.mybatis.demo.mapper"/>
    </mappers>

3.编写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.mybatis.demo.mapper.UserInfoMapper">

    <!-- 定义 sql 片段 -->
    <sql id="selectUserByUserNameAndSexSQL">
        <if test="username != null and username != ''">
            AND username = #{username}
        </if>
        <if test="sex != null and sex != ''">
            AND sex = #{sex}
        </if>
    </sql>
    <!-- 根据 id 查询 user_info 表中的数据
      id:唯一标识符,此文件中的id值不能重复
      resultType:返回值类型,一条数据库记录也就对应实体类的一个对象
      parameterType:参数类型,也就是查询条件的类型
   -->
    <!--在配置文件 mybatis-config.xml 中如果没有配置别名,则需要写全类名-->

    <select id="selectUserInfoByUsernameAndSex" resultType="UserInfo" parameterType="UserInfo">
        select * from user_info
        <trim prefix="where" prefixOverrides="and | or">

            <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
            <include refid="selectUserByUserNameAndSexSQL"></include>
            <!-- 在这里还可以引用其他的 sql 片段 -->
        </trim>
    </select>


    <!-- 根据 id 更新 user_info 表的数据 -->
    <update id="updateUserInfoById" parameterType="UserInfo">
        update user_info u
        <!--prefix:标签; suffixOverrides:去掉最后一个逗号(也可以是其他的标记)-->
        <trim prefix="set" suffixOverrides=",">
            <if test="username != null and username != ''">
                u.username = #{username},
            </if>
            <if test="sex != null and sex != ''">
                u.sex = #{sex},
            </if>
        </trim>
        where id=#{id}
    </update>


    <select id="selectUserInfoByChoose" resultType="UserInfo" parameterType="UserInfo">
        select * from user_info
        <where>
            <choose>
                <when test="id !='' and id != null">
                    id=#{id}
                </when>
                <when test="username !='' and username != null">
                    and username=#{username}
                </when>
                <otherwise>
                    and sex=#{sex}
                </otherwise>
            </choose>
        </where>
    </select>


    <select id="selectUserByListId" parameterType="com.mybatis.demo.model.UserInfoForm" resultType="UserInfo">
        select * from user_info
        <where>
            <!--
                collection:指定输入对象中的集合属性
                item:每次遍历生成的对象
                open:开始遍历时的拼接字符串
                close:结束时拼接的字符串
                separator:遍历对象之间需要拼接的字符串
                select * from user where 1=1 and id in (1,2,3)
              -->
            <foreach collection="ids" item="id" open="and id in (" close=") " separator=",">
                #{id}
            </foreach>
        </where>
    </select>


    <select id="selectUserInfoById" resultType="UserInfo" parameterType="int">
        <!-- 这里和普通的sql 查询语句差不多,对于只有一个参数,后面的 #{id}表示占位符,里面不一定要写id,写啥都可以,但是不要空着,如果有多个参数则必须写pojo类里面的属性 -->
        select * from user_info where id = #{id}
    </select>

    <select id="selectUserInfoAll" resultType="UserInfo">
        select * from user_info
    </select>

    <select id="selectLikeUserName" resultType="UserInfo" parameterType="String">
        select * from user_info where username like '%${value}%'
        <!-- select * from user where username like #{username} -->
    </select>

    <!-- 向 user_info 表插入一条数据 -->
    <insert id="insertUserInfo" parameterType="UserInfo">
        insert into user_info(id,username,password,high,age,sex)
            value(#{id},#{username},#{password},#{high},#{age},#{sex})
    </insert>
    
    <!-- 根据 id 删除 user_info 表的数据 -->
    <delete id="deleteUserInfoById" parameterType="int">
        delete from user_info where id=#{id}
    </delete>
</mapper>

4.测试

package com.mybatis.demo.mapper;

import com.mybatis.demo.model.UserInfo;
import com.mybatis.demo.model.UserInfoForm;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

/**
 * @auther kklu
 * @date 2019/9/29 15:49
 * @describe
 */

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class UserInfoMapperTest {
    private static SqlSessionFactory sqlSessionFactory;
    private static SqlSession sqlSession = null;
    private static UserInfoMapper userInfoMapper;

    @BeforeClass
    public static void init() {
        try {
            //将工具类读入 reader
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            //创建 SqlSessionFactory 对象,该对象包含了mybatis-config.xml相关配置信息
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            sqlSession = sqlSessionFactory.openSession();
            userInfoMapper = sqlSession.getMapper(UserInfoMapper.class);
            reader.close();
        } catch (IOException ignore) {
            ignore.printStackTrace();
        }
    }


    @Test
    public void testSelectUserInfoByUsernameAndSex() {
        try {
            UserInfo userInfo = new UserInfo();
            userInfo.setUsername("Jack");
            userInfo.setSex(1);
            List<UserInfo> result = userInfoMapper.selectUserInfoByUsernameAndSex(userInfo);
            log.info("result={}", result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }


    //根据 id 更新 user 表的数据
    @Test
    public void testUpdateUserInfoById() {
        try {
            //如果设置的 id不存在,那么数据库没有数据更改
            UserInfo userInfo = new UserInfo();
            userInfo.setId(4L);
            userInfo.setUsername("令狐冲");
//            userInfo.setSex(1);
            userInfoMapper.updateUserInfoById(userInfo);
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }


    //根据 id 更新 user 表的数据
    @Test
    public void testSelectUserInfoByChoose() {
        try {
            UserInfo userInfo = new UserInfo();
//            userInfo.setId(4L);
//            userInfo.setUsername("Text");
            userInfo.setSex(1);
            List<UserInfo> listUser = userInfoMapper.selectUserInfoByChoose(userInfo);
            for (UserInfo info : listUser) {
                log.info("info={}", info);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }

    @Test
    public void testSelectUserByListId() {
        try {
            UserInfoForm userInfoForm = new UserInfoForm();
            List<Integer> ids = new ArrayList<>();
            ids.add(1);
            ids.add(2);
            ids.add(3);
            ids.add(50);
            userInfoForm.setIds(ids);
            List<UserInfo> listUser = userInfoMapper.selectUserByListId(userInfoForm);
            for (UserInfo info : listUser) {
                log.info("info={}", info);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }


    @Test
    public void testSelectUserInfoById() {
        try {
            UserInfo listUser = userInfoMapper.selectUserInfoById(4);
            log.info("info={}", listUser);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }

    @Test
    public void testSelectUserInfoAll() {
        try {
            List<UserInfo> listUser = userInfoMapper.selectUserInfoAll();
            for (UserInfo info : listUser) {
                log.info("info={}", info);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }


    @Test
    public void testSelectLikeUserName() {
        try {
            List<UserInfo> listUser = userInfoMapper.selectLikeUserName("明");
            for (UserInfo userInfo : listUser) {
                log.info("userInfo={}", userInfo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }


    //向 user 表中插入一条数据
    @Test
    public void testInsertUserInfo() {
        try {
            UserInfo userInfo = new UserInfo();
            userInfo.setUsername("王二");
            userInfo.setPassword("123456");
            userInfo.setSex(1);
            userInfo.setAge(21);
            userInfo.setHigh(175);
            userInfoMapper.insertUserInfo(userInfo);
            //提交插入的数据
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }


    //根据 id 删除 user 表的数据
    @Test
    public void testDeleteUserInfoById() {
        try {
            userInfoMapper.deleteUserInfoById(1);
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }
}

5.注意事项

在这里插入图片描述

  1. UserInfoMapper.xml 中的命名空间是接口的全类名,否则会找不到
  2. UserInfoMapper.java 接口与 UserInfoMapper.xml 所在的包名要一致,其中 UserInfoMapper.xml 也可以放在reourcces 下面,但是要建一个相同的包名
  3. UserInfoMapper.java 接口中的方法要与 UserInfoMapper.xml 中定义的id保持一致
  4. UserMapper接口输入参数类型要和 UserMapper.xml 中定义的 parameterType 一致
  5. UserMapper接口返回数据类型要和 UserMapper.xml 中定义的 resultType 一致

6.总结

简单总结下使用MyBatis的几种方式

  1. 接口可以单独使用
  2. 注解不能单独使用,必须结合接口使用
  3. 接口不能单独使用,可以结合XML 或者注解使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值