MyBatis 单表的增删改查

news2024/11/29 10:51:57

在这里插入图片描述

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。
🍎个人主页:Java Fans的博客
🍊个人信条:不迁怒,不贰过。小知识,大智慧。
💞当前专栏:SSM 框架从入门到精通
✨特色专栏:国学周更-心性养成之路
🥭本文内容:MyBatis 单表的增删改查

本文目录

    • 结果映射 ResultMap
    • 使用 selectOne 方法查询单条记录
    • 使用 insert 方法添加记录
      •  主键非自增长
      •  主键值由数据库自增长
    • 使用 delete 方法删除记录
    • 使用 update 方法修改记录
    • 模糊查询
    • 动态查询
      •  if 标签
      •  where 标签
      •  set 标签
      •  trim 标签
      •  使用 Map 封装查询条件
      •  choose 标签
      •  foreach 标签
      •  sql 标签
    • mybatis分页插件
    • getMapper 面向接口编程
    • 多参数查询

在这里插入图片描述

  通过上一篇文章的学习可了解到,MyBatis 可以方便的对数据库进行操作,而数据库表可能是一个相对独立的表(这里谓之单表),也可能两个或多个有密切联系的表(这里谓之多表),本文先来学习单表的增删改查操作,下一篇文章我们再来学习多表关联查询。

  先来认识一下 SqlSession 的若干方法,这些方法被用来执行定义在 mapper 映射文件中的 SELECTINSERTUPDATEDELETE 语句。以下是一些常用的方法。

  • <T> T selectOne(String statement, Object parameter) 查询单条记录
  • <E> List selectList(String statement, Object parameter) 查询记录集合
  • <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey) 查询记录封装成 Map 集合
  • int insert(String statement, Object parameter) 插入一条记录
  • int update(String statement, Object parameter) 修改一条记录
  • int delete(String statement, Object parameter) 删除一条记录

  上述方法中的第一个参数 statement 通常使用 namespace + id 的字符串,namespace 定位到唯一的 mapper 映射文件,id 定位到这个 mapper 映射文件指定的 SQL 语句。

  第二个参数可以是原生类型(自动装箱或包装类)、JavaBeanPOLOMap,用于限定查询条件等。

  其中 selectOneselectList 的不同之处是 selectOne 必须返回一个对象,如果有多个对象,或者没有返回(或返回了 null),那么就会抛出异常。如果不确定返回了多少对象,就使用 selectList

以上方法可以重载,第二个参数不是必要的,重载方法如下。

  • <T> T selectOne(String statement)
  • <E> List<E> selectList(String statement)
  • <K,V> Map<K,V> selectMap(String statement, String mapKey)
  • int insert(String statement)
  • int update(String statement)
  • int delete(String statement)

结果映射 ResultMap

  所谓结果映射就是让数据表的字段名称(即列名)与 Java 实体类的属性名称一一进行关联匹配的一种机制,以便 MyBatis 查完数据库后能将关系型查询结果正确地封装为 Java 对象。如果数据库的字段名称跟相应的类的属性名称不一样,不作处理的话,mybatis 运行后相应的字段处的查询结果就为空。

  在映射文件 UserMapper.xml 中,如果 SQL 查询语句使用别名了,则 <select> 节点中的 SQL 查询语句修改如下:

    <select id="list" resultType="user">
        select * from user
    </select>

  然后运行 UserMapperTest.java 测试类中的 testList 方法:

    @Test
    public void testList() {
        SqlSession sqlSession = factory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = mapper.list();
        for (User user : list) {
            System.out.println("user = " + user);
        }
    }

  运行结果如下:

在这里插入图片描述
  可以发现查出来的数据为 null,这是因为数据表 user 的字段与对象 User 的属性名称不一致造成的。数据库查出来的数据无法封装到对应的对象属性中去。

解决办法有两个:

  • 方法一:在 SQL 语句中使用别名,让查询结果字段与对象属性一致
  • 方法二:利用结果映射 ResultMap

  在 UserMapper.xml 中配置结果映射 ResultMap,代码如下:

    <!--定义映射规则-->
    <resultMap id="userMap" type="user">
        <id column="u_id" property="id"></id>
        <result column="u_name" property="userName"></result>
        <result column="u_password" property="password"></result>
    </resultMap>
    <select id="list" resultMap="userMap">
        select * from user
    </select>

  上面代码中,将原先的 resultType=“user” 改为了 resultMap=“userMap”,其中,userMap为 结果映射 resultMap 中的 id

  运行原有的测试类,效果如下:

在这里插入图片描述
  可以正常输出了,没有出现 null 的情况,证明了结果映射成功。

使用 selectOne 方法查询单条记录

实现步骤:

  【1】在 UserMapper.java 接口中新增一个方法:

User getById(Integer id);

  【2】在映射文件 UserMapper.xml 中新增一段 select 语句:

    <select id="getById" parameterType="int" resultMap="userMap">
        select * from user where u_id=#{id}
    </select>

  其中,parameterType=“int” 表示参数的类型为整型,也可省略不用,MyBatis 会自动识别传进来的参数类型。此外仍然使用结果映射 resultMap

  <select> 标签中的 id 属性用于唯一标识该 SQL 语句,要与接口中方法名称一致。SQL语句中的 #{ }:对指定参数类型属性值的引用。

  【3】在测试类 UserMapperTest.java 中添加 testGetById 方法,代码如下:

    @Test
    public void testGetById() {
        SqlSession sqlSession = factory.openSession(true);
        User user = sqlSession.selectOne("cn.kgc.mybatis.mapper.UserMapper.getById", 1);
        System.out.println(user);
    }

  sqlSession.selectOne 方法,用于查询单条数据,其中第一个参数是 UserMapper.java 接口中 getById 方法的全限定名,第二个参数是 id 值。

  运行结果如下:

在这里插入图片描述

使用 insert 方法添加记录

 主键非自增长

实现步骤:

  【1】检查数据库 user 表,将主键 u_id 改为非自增长,然后在 UserMapper.java 接口中新增一个方法。

	int insertUser(User user);

  【2】在映射文件 UserMapper.xml 中新增一段 insert 语句。

    <!--添加一个用户-->
    <insert id="insertUser" parameterType="user">
        insert into user (u_id,u_name,u_password) values (#{id},#{userName},#{password})
    </insert>

  parameterType=“user” 也可不加,MyBatis 会自动判断传进来的参数类型。#{id} 是占位符,传进来的值是参数类型 User 对应的同名属性值,即 User 对象的 id 属性的值,其他类推。

  【3】在测试类 UserMapperTest.java 中添加 testGetById 方法,代码如下:

    @Test
    public void testInsertUser(){
        SqlSession sqlSession = factory.openSession(true);
        User user=new User();
        user.setId(4);
        user.setUserName("武松");
        user.setPassword("12345");
        int count = sqlSession.insert("cn.kgc.mybatis.mapper.UserMapper.insertUser", user);
        sqlSession.commit();
        System.out.println(count);
    }

  这里用到 insert 方法,用于添加记录,返回受影响的行数。运行效果如下:

在这里插入图片描述
在这里插入图片描述
  注意: 如果数据库中没有发现这条新纪录,可能是因为你没有使用 sqlSession.commit() 方法来实现事务提交。

 主键值由数据库自增长

  MySQL 数据库表的主键值在设置为自动增长的情况下,程序只需要添加除主键外的其他字段即可。但一般情况下程序中添加一个 User 对象后无法马上获得该对象的 id 属性值,需要一定的配置才行,具体步骤如下:

  【1】修改 MySQL 数据库,设置 user 表的主键 u_id 自动增长。

在这里插入图片描述

  注意:这里用的 MySQL 客户端是 SQLyog

  【2】在 UserMapper.java 接口中新增一个方法。

	int insertUserAutoIncrement(User user);

  【3】在映射文件 UserMapper.xml 中新增一段 insert 语句。

    <!--添加一个用户,u_id自增-->
    <insert id="insertUserAutoIncrement">
        insert into user (u_name,u_password) values (#{userName},#{password})
    </insert>

  【4】在测试类 UserMapperTest.java 中添加 testInsertUserAuto 方法,代码如下:

	@Test
    public void testInsertUserAuto(){
        SqlSession sqlSession = factory.openSession(true);
        User user=new User();
        user.setUserName("武松");
        user.setPassword("12345");
        int count = sqlSession.insert("cn.kgc.mybatis.mapper.UserMapper.insertUserAutoIncrement", user);
        sqlSession.commit();
        if(count>0){
            System.out.println("添加成功!");
            System.out.println("新添加的学生编号是:"+user.getId());
        }
    }

  运行结果如下:

在这里插入图片描述

  可见添加时成功的,但添加后学生编号为0,即无法在添加完数据后立即回去主键的值,如何在数据添加成功后获取这个自增长的主键值呢?请看下一个步骤。

  【5】修改映射文件,代码如下:

    <!--添加一个用户,u_id自增-->
    <insert id="insertUserAutoIncrement" parameterType="user"
    keyProperty="id" useGeneratedKeys="true">
        insert into user (u_name,u_password) values (#{userName},#{password})
    </insert>

  关键代码是 keyProperty=“id” useGeneratedKeys=“true”,其中,keyProperty 指的是实体类的某个属性接受接受主键返回的值,useGeneratedKeys 指的是使用自动生成的主键。

  【6】二次测试,代码如下:

    @Test
    public void testInsertUserAuto(){
        SqlSession sqlSession = factory.openSession(true);
        User user=new User();
        user.setUserName("苏东坡");
        user.setPassword("32154");
        int count = sqlSession.insert("cn.kgc.mybatis.mapper.UserMapper.insertUserAutoIncrement", user);
        sqlSession.commit();
        if(count>0){
            System.out.println("添加成功!");
            System.out.println("新添加的用户编号是:"+user.getId());
        }
    }

  二次测试结果如下:

在这里插入图片描述

  可以发现,已经获取到新添加的用户的主键值。

使用 delete 方法删除记录

实现步骤:

  【1】在 UserMapper.java 接口中新增一个方法 deleteUserById 如下:

    int deleteUserById(Integer id);

  【2】在映射文件 UserMapper.xml 中新增一段 delete 语句如下:

    <!--删除一个用户-->
    <delete id="deleteUserById">
        delete from user where u_id=#{id}
    </delete>

  【3】在测试类 UserMapperTest.java 中添加 testDeleteUserById 方法,代码如下:

    @Test
    public void testDeleteUserById(){
        SqlSession sqlSession = factory.openSession(true);
        int count = sqlSession.delete("cn.kgc.mybatis.mapper.UserMapper.deleteUserById", 4);
        sqlSession.commit();
        if(count>0){
            System.out.println("删除成功!");
        }else{
            System.out.println("用户不存在!");
        }
    }

  运行效果如下:

在这里插入图片描述

使用 update 方法修改记录

实现步骤:

  【1】在 UserMapper.java 接口中新增一个方法 updateUserById 如下:

    int updateUserById(User user);

  【2】在映射文件 UserMapper.xml 中新增一段 update 语句如下:

    <!--更新用户信息-->
    <update id="updateUserById">
        update user set u_name=#{userName},u_password=#{password} where u_id=#{id}
    </update>

  【3】在测试类 UserMapperTest.java 中添加 updateUserById 方法,代码如下:

    @Test
    public void testUpdateUserById(){
        SqlSession sqlSession = factory.openSession(true);
        User user=new User();
        user.setUserName("苏东");
        user.setPassword("123456");
        user.setId(7);
        int count = sqlSession.update("cn.kgc.mybatis.mapper.UserMapper.updateUserById", user);
        sqlSession.commit();
        if(count>0){
            System.out.println("更新成功!");
        }else{
            System.out.println("用户不存在!");
        }
    }

  运行效果如下:

在这里插入图片描述
在这里插入图片描述

模糊查询

实现步骤:

  【1】在 UserMapper.java 接口中新增一个方法 findUserByName 如下:

    List<User> findUserByName(String userName);

  【2】在映射文件 UserMapper.xml 中新增一段 select 语句如下:

    <!--根据姓名模糊查询-->
    <select id="findUserByName" resultType="cn.kgc.mybatis.entity.User" resultMap="userMap">
        select * from user where u_name like '%' #{userName} '%'
    </select>

  【3】在测试类 UserMapperTest.java 中添加 testFindUserByName 方法,代码如下:

    @Test
    public void testFindUserByName(){
        SqlSession sqlSession = factory.openSession(true);
        List<User> list = sqlSession.selectList("cn.kgc.mybatis.mapper.UserMapper.findUserByName", "张");
        for (User user : list) {
            System.out.println("user = " + user);
        }
    }

  运行效果如下:

在这里插入图片描述

动态查询

  在大家熟悉的网购中,筛选商品是一个非常重要的功能。筛选条件有很多,每个人选的条件都不一样,这里就用到了动态查询。前台页面把某个用户的筛选条件传到后台服务器,后台服务器根据筛选条件动态生成 SQL 语句,再从数据库中查找到合适商品。

  动态 SQL 多用于解决查询条件不确定的情况,在程序运行期间,根据运行期间,根据用户提交的多种可能的查询条件进行查询,提交的查询条件不同,动态生成和执行的 SQL 语句也不同。动态 SQL 通过 MyBatis 提供的各种标签对条件做出判断以实现动态拼接 SQL 语句。

  常用的动态 SQL 标签有 <if>、<where>、<set>、<choose/>、<foreach> 等。

  映射文件 UserMapper.xml 中定义映射规则,代码如下:

    <!--定义映射规则-->
    <resultMap id="userMap" type="user">
        <id column="u_id" property="id"></id>
        <result column="u_name" property="userName"></result>
        <result column="u_password" property="password"></result>
        <result column="u_state" property="state"></result>
    </resultMap>

 if 标签

  对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片段拼接到其所在的 SQL 语句中。

实现步骤:

  【1】在接口 UserMapper.java 中 添加方法 selectUserIf 如下:

	List<User> selectUserIf(@Param("userName") String userName, @Param("state") int state);

  【2】在映射文件 UserMapper.xml 中添加一条 select 语句,代码如下:

    <select id="selectUserIf" resultMap="userMap">
        select * from user where 1=1
        <if test="userName!=null">
            and u_name like '%' #{userName} '%'
        </if>
        <if test="state!=null">
            and u_state=#{state}
        </if>
    </select>

  【3】在测试类 UserMapperTest.java 中添加 testSelectUserIf 方法,代码如下:

    @Test
    public void testSelectUserIf() {
        SqlSession sqlSession = factory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.selectUserIf("张", 1);
        for (User user : users) {
            System.out.println("user = " + user);
        }
    }

  查询姓名中含有“张”字,并且 state 状态为1的记录,结果如下:

在这里插入图片描述

 where 标签

  <if/>标签的中存在一个比较麻烦的地方,需要在 where 后手工添加 “1=1” 的子句。因为,若 where 后的所有<if/>条件均为 falsewhere 后没有 1=1 子句的话,则 SQL 中就会只剩下一个空的 whereSQL 出错。可以使用<where>标签实现同样的效果,而无须 “1=1” 这个看起来额外的东西。

实现步骤:

  【1】在接口 UserMapper.java 中 添加方法 selectUserWhere 如下:

	List<User> selectUserWhere(@Param("userName") String userName, @Param("state") int state);

  【2】在映射文件 UserMapper.xml 中添加一条 select 语句,代码如下:

    <select id="selectUserWhere" resultMap="userMap">
        select * from user
        <where>
            <if test="userName!=null">
                and u_name like '%' #{userName} '%'
            </if>
            <if test="state!=null">
                and u_state=#{state}
            </if>
        </where>
    </select>

  【3】在测试类 UserMapperTest.java 中添加 testSelectUserIf 方法,代码如下:

    @Test
    public void testSelectUserWhere() {
        SqlSession sqlSession = factory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.selectUserIf("张", 1);
        for (User user : users) {
            System.out.println("user = " + user);
        }
    }

  查询姓名中含有“张”字,并且 state 状态为1的记录,结果如下:

在这里插入图片描述

 set 标签

  <set>标签用于更新操作的 update 语句中

实现步骤:

  【1】在接口 UserMapper.java 中 添加方法 updateUserSet 如下:

	Integer updateUserSet(User user);

  【2】在映射文件 UserMapper.xml 中添加一条 **update ** 语句,代码如下:

    <update id="updateUserSet">
        update user
        <set>
            <if test="userName!=null">
                u_name = #{userName}
            </if>
            <if test="password!=null">
                ,u_password=#{password}
            </if>
            <if test="state!=null">
                ,u_state = #{state}
            </if>
        </set>
        where u_id = #{id}
    </update>

  【3】在测试类 UserMapperTest.java 中添加 testUpdateUserSet 方法,代码如下:

    @Test
    public void testUpdateUserSet() {
        SqlSession sqlSession = factory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setPassword("888888");
        user.setState(1);
        user.setUserName("李清照");
        user.setId(2);
        Integer integer = mapper.updateUserSet(user);
        System.out.println("line = " + integer);
    }

  运行效果:

在这里插入图片描述
在这里插入图片描述

 trim 标签

  trim标记是一个格式化的标记,可以完成set或者是where标记的功能

  用 trim 改写上面的 if+where 语句

    <select id="selectUserWhere" resultMap="userMap">
        select *  from user
        <trim prefix="where" prefixOverrides="">
            <if test="userName!=null">
                 and u_name like '%' #{userName} '%'
             </if>
            <if test="state!=null">
               and u_state=#{state}
            </if>
        </trim>
    </select>
  • prefix:前缀
  • prefixoverride:去掉第一个and或者是or

  用 trim 改写上面的 if+set 语句

    <update id="updateUserSet">
        update user
        <trim prefix="set" suffixOverrides=",">
            <if test="userName!=null">
                u_name = #{userName}
            </if>
            <if test="password!=null">
                ,u_password=#{password}
            </if>
            <if test="state!=null">
                ,u_state = #{state}
            </if>
        </trim>
        where u_id = #{id}
    </update>
  • suffix:后缀
  • suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)

 使用 Map 封装查询条件

  上面几个案例中,多个查询条件都封装到一个 User 对象的属性中去了,但实际开发中,可能有些条件无法封装到同一个对象中去,这时可以采用 Map 类型进行封装和传递参数。

实现步骤:

  【1】在接口 UserMapper.java 中 添加方法 searchUsersMap 如下:

	List<User> searchUsersMap(Map map);

  【2】在映射文件 UserMapper.xml 中添加一条 select 语句,代码如下:

    <select id="searchUsersMap" resultMap="userMap">
        select * from user
        <where>
            <if test="userName!=null">
                and u_name like '%' #{userName} '%'
            </if>
            <if test="state!=null">
                and u_state=#{state}
            </if>
        </where>
    </select>

  【3】在测试类 UserMapperTest.java 中添加 testUpdateUserSet 方法,代码如下:

    @Test
    public void testSearchUsersMap() {
        SqlSession sqlSession = factory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("userName", "张");
        map.put("state", 1);
        List<User> users = mapper.searchUsersMap(map);
        for (User user : users) {
            System.out.println("user = " + user);
        }
    }

  运行效果:

在这里插入图片描述

 choose 标签

  该标签里面包含 <when/> <otherwise/> 两个子标签,可以包含多个 <when/> 与一个 <otherwise/>。它们联合使用,完成类似 Java 中的开关语句 switch…case 功能。

实现步骤:

  【1】在接口 UserMapper.java 中 添加方法 searchUsersMap 如下:

	List<User> searchUsersChoose(User user);

  【2】在映射文件 UserMapper.xml 中添加一条 select 语句,代码如下:

    <select id="searchUsersChoose" resultMap="userMap">
        select * from user
        <where>
            <choose>
                <when test="userName!=null">
                    and u_name like '%' #{userName} '%'
                </when>
                <when test="state!=null">
                    and u_state=#{state}
                </when>
                <otherwise>
                    and 1!=1
                </otherwise>
            </choose>
        </where>
    </select>

  <choose/> 标签会从第一个 <when/> 开始,逐个向后进行条件判断。若出现 <when/> 中 test 属性值为 true 的情况,就直接结束 <choose/> 标签,不再向后进行判断查找。若所以 <when/> 的 test 判断结果均为 false,则最后会执行 <otherwise/> 标签。这种功能类似于 switch,实现了分支选择。

  【3】在测试类 UserMapperTest.java 中添加 testUpdateUserSet 方法,代码如下:

    @Test
    public void testSearchUsersChoose() {
        SqlSession sqlSession = factory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User usr=new User();
        usr.setUserName("张");
        usr.setState(1);
        List<User> users = mapper.searchUsersChoose(usr);
        for (User user : users) {
            System.out.println("user = " + user);
        }
    }

  运行效果:

在这里插入图片描述

 foreach 标签

  <foreach/>标签用于实现对数组与集合类型的输入参数的遍历。其 collection 属性表示要遍历的集合类型,如果是数组,其值就用 arrayopencloseseparator 这些属性用于对遍历内容进行 SQL 拼接。

  需求:我们需要查询 user 表中 id 分别为1,2,3的用户,sql 语句:

	select * from user where id=1 or id=2 or id=3

	select * from user where id in (1,2,3)

  用 foreach 来改写 select * from user where id=1 or id=2 or id=3

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

  用 foreach 来改写 select * from user where id in (1,2,3)

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

 sql 标签

  有时候可能某个 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>
<select id="selectUserByUsernameAndSex" resultType="user" parameterType="com.ys.po.User">
    select * from user
    <trim prefix="where" prefixOverrides="and | or">
        <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
        <include refid="selectUserByUserNameAndSexSQL"></include>
        <!-- 在这里还可以引用其他的 sql 片段 -->
    </trim>
</select>

  注意:

  • ①、最好基于 单表来定义 sql 片段,提高片段的可重用性
  • ②、在 sql 片段中最好不要包括 where

mybatis分页插件

	<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
	<dependency>
	    <groupId>com.github.pagehelper</groupId>
	    <artifactId>pagehelper</artifactId>
	    <version>5.2.1</version>
	</dependency>
	<!--在mybatis配置文件中 配置mybatis插件 -->
	<plugins>
		<plugin interceptor="com.github.pagehelper.PageInterceptor">
			<!-- 配置mysql方言 -->
			<property name="helperDialect" value="mysql" />
			<!-- 设置为true时,如果pageSize=0就会查询出全部的结果 -->
			<property name="pageSizeZero" value="true" />
			<!-- 3.3.0版本可用,分页参数合理化,默认false禁用 -->
			<!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
			<!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
			<property name="reasonable" value="true" />
		</plugin>
	</plugins>

实例

 	// 测试分页插件的使用
    @Test
    public void  test06(){
        SqlSession session = factory.openSession(true);
        StudentDao mapper = session.getMapper(StudentDao.class);
        PageHelper.startPage(5, 3);
        List<Student> all = mapper.findAll();
        PageInfo<Student> pageInfo = new PageInfo<>(all);

        //获取分页的相关数据
        System.out.println(pageInfo);
        //获取总条数
        long total = pageInfo.getTotal();
        System.out.println(total);
        //获取当前页的显示数据
        List<Student> list = pageInfo.getList();
        list.forEach(student-> System.out.println(student));

    }

getMapper 面向接口编程

  之前我们自定义 Dao 层接口实现类时发现一个问题:Dao 层的实现类其实并没有干什么实质性的工作,它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 idSQL 语句,真正对数据进行操作的工作其实是由框架通过映射文件 mapper 中的 SQL 完成的。

  那么,MyBatis 框架可以抛开 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对数据库进行操作吗?答案是肯定的。可以通过Mapper的动态代理方式实现

实现步骤如下图目录结构所示:

在这里插入图片描述

  • 注意:
    • 确保映射文件 UserMapper.xmlnamespace 与接口类的全路径名称一致;
    • resources 中创建目录时,注意目录间用 / 分割,如创建 cn.kgc.mybatis04.mapper ,创建 Directory 时,写法为:cn/kgc/mybatis04/mapper,这样就可以准确创建目录结构。

多参数查询

  上面的案例中要传多个参数,把这些参数都巧妙的封装成一个对象或一个 Map,表面上还是一个参数。有时想直接传递多个参数,而不想封装,如何实现?

实现步骤:

  【1】在接口 UserMapper.java 中 添加方法 selectUserWhere 如下:

	List<User> selectUserWhere(@Param("userName") String userName, @Param("state") int state);

  这里用到了 @Param 注解。映射文件的 SQL 语句中的输入参数应与注解里面的参数一致。

  【2】在映射文件 UserMapper.xml 中添加一条 select 语句,代码如下:

	<!--多参数查询-->
    <select id="selectUserWhere" resultMap="userMap">
        select * from user where u_name like '%' #{userName} '%' and u_state=#{state}
    </select>

  码文不易,本篇文章就介绍到这里,如果想要学习更多Java系列知识点击关注博主,博主带你零基础学习Java知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/335407.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在多线程环境下使用哈希表

一.HashTable和HashMapHashTable是JDK1.0时创建的&#xff0c;其在创建时考虑到了多线程情况下存在的线程安全问题&#xff0c;但是其解决线程安全问题的思路也相对简单&#xff1a;在其众多实现方法上加上synchronized关键字&#xff08;效率较低&#xff09;&#xff0c;保证…

《SOC芯片研究框架》深度科普,发展趋势、技术特点、产业链一文看懂

片上系统SoC&#xff08;System on Chip&#xff09;&#xff0c;即在一块芯片上集成一整个信息处理系统&#xff0c;简单来说 SoC芯片是在中央处理器CPU的基础上扩展音视频功能和专用接口的超大规模集成电路&#xff0c;是智能设备的“大脑”。随着半导体工艺的发展&#xff0…

Typescript - interface 关键字(通俗易懂的详细教程)

前言 简单来说&#xff0c;Interface 就是一种描述对象或函数的东西。 您可以把 interface 理解为形状&#xff0c;真实开发情况下&#xff0c;一个对象需要有什么样的属性&#xff0c;函数需要什么参数或返回什么样的值&#xff0c;数组应该是什么样子的&#xff0c;一个类和继…

MySQL慢查询分析和性能优化

1 背景我们的业务服务随着功能规模扩大&#xff0c;用户量扩增&#xff0c;流量的不断的增长&#xff0c;经常会遇到一个问题&#xff0c;就是数据存储服务响应变慢。导致数据库服务变慢的诱因很多&#xff0c;而RD最重要的工作之一就是找到问题并解决问题。下面以MySQL为例子&…

矢量网络分析仪介绍

矢量网络分析仪VNA是一种测试仪器&#xff0c;它可以将网络的响应测量成矢量:实参数和虚参数&#xff0c;从而表征其性能。矢量网络分析仪VNA是射频设计实验室和许多制造和服务领域的重要测试仪器。虽然矢量网络分析仪主要侧重于研究和开发&#xff0c;但它也可以为所有类型的R…

想要精通算法和SQL的成长之路 - 柱状图中最大的矩形

想要精通算法和SQL的成长之路 - 柱状图中最大的矩形前言一. 柱状图中最大的矩形前言 想要精通算法和SQL的成长之路 - 系列导航 一. 柱状图中最大的矩形 原题链接 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。求…

你是真的“C”——操作符详解【下篇】+整形提升+算术转换

你是真的“C”——操作符详解下篇&#x1f60e;前言&#x1f64c;操作符详解【上篇】内容&#xff1a;操作符详解【下篇】内容&#xff1a;1、 条件操作符2、逗号表达式&#xff1a;3、下标引用、函数调用和结构成员3、访问一个结构的成员表达式求值1、隐式类型转换&#xff1a…

扫雷——C语言【详解+全部码源】

前言&#xff1a;今天我们学习的是C语言中另一个比较熟知的小游戏——扫雷 下面开始我们的学习吧&#xff01; 文章目录游戏整体思路游戏流程游戏菜单的打印创建数组并初始化布置雷排查雷完整代码game.hgame.ctest.c游戏整体思路 我们先来看一下网上的扫雷游戏怎么玩 需要打印…

Imported target “dart“ includes non-existent path 笔记

详细问题&#xff1a;关联功能包&#xff0c;源码编译Failed <<< gazebo_ros2_control [11.8s, exited with code 1]网上查了很多资料&#xff0c;都是比较旧版&#xff0c;这里注意由于ROS2系统发展很快&#xff0c;功能包在快速集成。使用源码编译可能会遇到环境配置…

PMP报考条件?

PMP已经被认为是项目管理专业身份的象征&#xff0c;项目经理人取得的重要资质。 PMP考试一般每年在中国大陆地区&#xff0c;会进行四次考试&#xff0c;今天就来详细说一说PMP考试的时间线。 01考试时间PMP考试在中国大陆一年开展四次&#xff0c;分别在每年的3月、6月、9月…

SpringCloud(17):Sentinel简介

1 流量控制&熔断降级介绍 1.1 流量控制简介 拿旅游景点举个示例&#xff0c;每个旅游景点通常都会有最大的接待量&#xff0c;不可能无限制的放游客进入&#xff0c;比如故宫每天只卖八万张票&#xff0c;超过八万的游客&#xff0c;无法买票进入&#xff0c;因为如果超过…

软件架构设计(二)——领域架构、基于架构的软件开发方法

目录 一、架构描述语言 ADL 二、特定领域软件架构 DSSA 三、DSSA的三层次架构模型 . 四、基于架构的软件开发方法 (1)基于架构的软件设计(ABSD) (2)开发过程 一、架构描述语言 ADL ADL是一种形式化语言&#xff0c;它在底层语义模型的支持下&#xff0c;为软件系统概念体…

云安全之浅谈密钥泄露

前言 如今越来越多公司选择使用云平台&#xff0c;诸如:阿里云、腾讯云、AWS、Azure。使用云平台大大降低了企业的资源成本&#xff0c;另一方面随着公用云的普及&#xff0c;也存在着一些风险。现代应用程序需要与其他外部应用程序通信&#xff0c;并且它们需要内部服务到服务…

ESP32设备驱动-模拟输入(ADC)

模拟输入(ADC) 文章目录 模拟输入(ADC)1、ADC介绍2、ADC相关API介绍3、软件准备4、硬件准备5、代码实现本文将介绍如何使用Arduino IDE对ESP32进行模拟读取。模拟读数可用于从可变电阻式电位计或模拟传感器读取值。 1、ADC介绍 ESP32有两个ADC单元,可用于以下场景: 生成…

Echarts的Category轴滑动

Echarts的Category轴滑动 效果&#xff0c;滚轮上下可拖动 配置项 dataZoom: [// {// // disabled: false,// start: 100, //默认为0// end: 80, //默认为100// // startValue: [xArr.length - 1],// // endValue: [xArr.length - 4],// type: slide…

typora每次复制文档都要附带图片文件夹?学会配置gitee图床

0. 引言 作为开发人员&#xff0c;我们习惯使用md格式来编写文档&#xff0c;特别是typora编辑器更是日常使用的软件。但作为轻量化的文档编辑器&#xff0c;我们在默认插入图片时&#xff0c;一般typora会将图片保存到本地或者引用一个本地图片的路径 当文档还在我们本地打开…

免费IB学习资源推荐,学霸常用

看了那些学霸们分享的笔记与网站&#xff0c;深刻认识到学习的竞争&#xff0c;就是对个人资源归纳整理能力的比拼&#xff0c;想要学好IB学科&#xff0c;除了跟着自己的辅导老师积极学习以外&#xff0c;还要学会充分掌握学习资料&#xff0c;这样才能做到心中有数&#xff0…

超清遥感影像语义分割处理

分割出城市中的垃圾堆场,遂寻找到了 UrbanAtlas 2012 database 这个数据集和对应的 baseline baseline IoU for class 1: 0.5667 IoU for class 2: 0.3504 IoU for class 3: 0.0001 IoU for class 4: 0.0002 IoU for class 5: 0.4121 IoU for class 6: 0.0204 IoU for cla…

第三章:IP地址加掩码讲解和ping命令运用

IP地址加掩码&#xff1a;我打几个IP地址给你们瞅瞅。10.20.70.55/24192.168.30.2/24我写的这几个都是24位掩码的&#xff0c;/后面的是掩码位数&#xff0c;也就是是255.255.255.0。子网掩码分为三类&#xff1a;A类&#xff1a;255.0.0.0B类&#xff1a;255.255.0.0C类&#…

RMIserver端和Registry端源码分析

想学JDNI&#xff0c;那想必一定躲不过RMI。 RMI简述 RMI可以远程调用JVM对象并获取结果。所以需要一个server和一个client进行通信。 Server端会创建一个远程对象用于client端远程访问。 下面改造一张来自W3Cschool的图&#xff1a; 只需要知道&#xff1a;Client端使用st…