使用MyBatis(2){使用myBatis操作增删改查/动态SQL}

本文围绕MyBatis展开,介绍了定义接口、实体类和创建XML文件实现接口的方法。详细阐述了MyBatis的增删改查操作,包括传递参数查询的两种写法及区别。还讲解了动态SQL的多种标签使用,最后提及了mybatisx插件报错、数据回滚和查询字段为null的问题及解决办法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、定义接口、实体类、创建XML文件实现接口)

二、MyBatis的增删改查 

🍅1、MyBatis传递参数查询

        🎈写法一

         🎈写法二

        🎈两种方式的区别

🍅2、删除操作

🍅3、根据id修改用户名

🍅4、添加用户操作

        🎈返回受影响的行数

        🎈返回自增id

🍅5、like查询

🍅6、多表查询

 三、动态SQL

        🍅 <if>标签

        🍅 <trim>标签

        🍅 <where>标签

        🍅 <set>标签

        🍅 <foreach>标签

四、注意

🍅1、mybatisx插件报错

🍅2、数据回滚

🍅 3、查询某字段结果为null时


一、定义接口、实体类、创建XML文件实现接口)

注意包名:

实体类

package com.example.demo.model;

import lombok.Data;

import java.time.LocalDateTime;

@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
    private String photo;
    private LocalDateTime updatatime;
    private LocalDateTime createtime;
    private int state;

}

接口

package com.example.demo.dao;

import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper  //数据持久层的标志
public interface UserMapper {
    List<UserInfo> getAll();
}

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.example.demo.dao.UserMapper">
<!--    id是UserMapper的方法名-->
    <select id="getAll" resultType="com.example.demo.model.UserInfo">
--         不写分号
            select * from userinfo
    </select>
</mapper>

二、MyBatis的增删改查 

🍅1、MyBatis传递参数查询

        🎈写法一

@Param("id")与${id}相互匹配 (及时执行)

使用id去查询某条数据(传参数)

UserInfo getUserById(@Param("id") Integer uid);
-- 这里应该写${id},而不是uid
<select id="getUserById" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where id=${id}
    </select>

测试类: 

@Test
    void getUserById() {
        UserInfo userInfo = userMapper.getUserById(1);
        System.out.println(userInfo.toString());
    }

         🎈写法二

@Param("id")与#{id}相互匹配 (预执行)

<select id="getUserById" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where id=#{id}
    </select>

        🎈两种方式的区别

1.${}是直接替换;而#{}是预执行

2.使用${}是不安全的,存在SQL注入;而#{}是安全的,不存在SQL注入

3.${}使用场景:当业务需要传递SQL语句时,只能使用${},不能使用#{}。

SQL注入:将SQL代码插入或添加到应用(用户)的输入参数中的攻击,之后再将这些参数传递给后台的sql服务器加以解析和执行。


🍅2、删除操作

UserInfo getUserById(@Param("id") Integer uid);
<!--    delete操作不需要设置返回类型-->
    <delete id="delById">
        delete from userinfo where id=#{id}
    </delete>

 测试类


    @Transactional   //数据回滚:使用该注解,会执行下面操作,但是不会真的操作数据库中的内容
    @Test
    void testGetUserById() {
        int id = 1;
        UserInfo result = userMapper.getUserById(id);
        System.out.println("受影响的行数:"+result);
    }

🍅3、根据id修改用户名

//    根据id修改用户名
//    返回受影响行数
    int update(UserInfo userInfo);
<!--    默认返回受影响的行数,不需要设置resultType-->
    <update id="update" >
        update userinfo set username=#{username} where id=#{id}
    </update>
@Transactional
    @Test
    void update() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setUsername("管理员");
        int result = userMapper.update(userInfo);
        System.out.println("受影响行数"+ result);
    }

 运行结果:


🍅4、添加用户操作

        🎈返回受影响的行数

//返回受影响字段
int add(UserInfo userInfo);
<insert id="add">
        insert into userinfo(username,password,photo) 
values (#{username},#{password},#{photo})
    </insert>
//测试类
@Test
    void add() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("张三");
        userInfo.setPassword("11111");
        userInfo.setPhoto("/image/default.png");
        int result = userMapper.add(userInfo);
        System.out.println("受影响的行数:"+ result);
    }

 运行结果:

        🎈返回自增id

    int insert(UserInfo userInfo);
<insert id="insert" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into userinfo(username,password,photo) values (#{username},#{password},#{photo})
    </insert>
//测试类 
@Test
    void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("李四");
        userInfo.setPassword("111111");
        userInfo.setPhoto("");
        int result = userMapper.insert(userInfo);
        System.out.println("受影响的行数:" + result +
                "| id:"+ userInfo.getId());
    }

 运行结果:

 对应关系:


🍅5、like查询

    List<UserInfo> getListByLike(@Param("username")String username);
<select id="getListByLike" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username like concat('%',#{username},'%')
    </select>
@Test
    void getListByLike() {
        String username = "三";
        List<UserInfo> list = userMapper.getListByLike(username);
        System.out.println(list);
    }

运行结果:


🍅6、多表查询

使用注解将sql语句和接口连接起来。

之前是,写一个接口就要写一个对应的xml文件编写sql语句。现在可以不使用这种方法

可以直接在接口中通过注解编写查询语句:

@Mapper
public interface ArticleMapper{
    @Select("select a.*,u.username from articleinfo a" +
    "left join userinfo u on a.uid=u.id")
    List<Articleinfo> getAll();
}

测试类:

class ArticleMapperTest {
    @Autowired
    private ArticleMapper articleMapper;
    @Test
    void getAll() {
        List<Articleinfo> list = articleMapper.getAll();
        System.out.println(list);
    }
}


 三、动态SQL

  动态SQL时MyBatis的强大特性之一,可以完成不同条件下的sql拼接,就是在XML文件中动态的去写判断条件。以下是一些动态标签:

        🍅 <if>标签

语法:

        <if test="photo!=null">

                ........

        </if>

//代码示例


int add2(UserInfo userinfo);


<insert id="add2">
        insert into userinfo(username,password
        <if test="photo!=null">
            ,photo
        </if>
        )values (#{username},#{password}
        <if test="photo!=null">
            ,#{photo}
        </if>
        )
    </insert>

        🍅 <trim>标签

<trim>标签中有如下属性:

        * prefix:表示整个语句块,以prefix的值作为前缀

        * suffix:表示整个语句块,以suffix的值作为后缀

        * prefixOverrides:表示整个语句块要去除掉的前缀

        * suffixOverrides:表示整个语句块要去除掉的后缀

int add3(UserInfo userInfo);


<insert id="add3">
        insert into userinfo
            <trim prefix="("  suffix=")" suffixOverrides=",">
                <if test="username!=null">
                    username,
                </if>
                <if test="password!=null">
                    password,
                </if>
                <if test="photo!=null">
                    photo
                </if>
            </trim>
            values
        <trim prefix="("  suffix=")" suffixOverrides=",">
            <if test="username!=null">
                #{username},
            </if>
            <if test="password!=null">
                #{password},
            </if>
            <if test="photo!=null">
                #{photo}
            </if>
        </trim>
    </insert>

        🍅 <where>标签

<where>标签:

        * 根据有<where>标签中的内容决定是否生成“where”关键字

        * 去除最前面的“and”关键字,不能去掉后面的

<!--    直接写select * from userinto where会报错,但是使用where标签就不会报错-->
    <select id="getListByWhere" resultType="com.example.demo.model.UserInfo">
        select * from userinfo
        <where>
            <if test="id!=0">
                id=#{id}
            </if>
            <if test="username!=null">
                and username=#{username}
            </if>
            <if test="password!=null">
                and password=#{password}
            </if>
        </where>
    </select>

使用<trim>标签也可以生成where

<select id="getListByWhere" resultType="com.example.demo.model.UserInfo">
        select * from userinfo    
    <trim prefix="where" prefixOverrides="and">
            <if test="id!=0">
                id=#{id}
            </if>
            <if test="username!=null">
                and username=#{username}
            </if>
            <if test="password!=null">
                and password=#{password}
            </if>
        </trim>
    </select>

        🍅 <set>标签

        和where标签使用一样

<update id="update2">
        update userinfo
        <set>
            <if test="username!=null">
                username=#{username},
            </if>
            <if test="password!=null">
                password=#{password},
            </if>
            <if test="photo!=null">
                photo=#{photo},
            </if>
        </set>
        where id=#{id}
    </update>

        🍅 <foreach>标签

MyBatis提供了<foreach>标签来处理动态SQL中的循环操作。这个标签允许你在SQL语句中迭代一个集合,并生成重复的SQL片段。

    <foreach>标签属性:

                * collection:绑定方法参数中的集合,如List,Set,Map或数组对象

                * item:遍历时的每一个对象

                * open:语句块开头的字符串

                * close:语句块结束的字符传

                * separator:每次遍历之间间隔的字符串 

以下例子可以看成是:

delete from userinfo where id in(?,?,?,?) 
    <delete id="delByIds">
        delete from userinfo
        where id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </delete>
//测试类
@Test
    void delByIds() {
        List<Integer> list = new ArrayList<Integer>(){{
            add(8);
            add(9);
            add(10);
            add(11);
        }};
        int result = userMapper.delByIds(list);
        System.out.println("result" + result);
    }

四、注意

🍅1、mybatisx插件报错

 以上并非系统报错,而是插件在报错,告诉我们没有设置返回的技术类型,高版本的idea遇到这种情况运行是不会报错的。

🍅2、数据回滚

 @Transactional   //数据回滚:使用该注解,会执行下面操作,但是不会真的操作数据库中的内容

🍅 3、查询某字段结果为null时

原因是:实体类中的属性和数据库表中的字段名不一致。

       解决方案:

        1.将实体类中的属性和表中的字段名保持一致(最简单的解决方案)

        2.使用sql语句中的as进行列名(字段名)重命名,让列名(字段名)等于属性名

<!--   加入要查询的字段名应该是name,对name进行重命名 -->
<selet id="getUserById" resultType="com.example.demo.model.UserInfo">
        select username as name from userinfo where id=#{id}c
    </select>

        3.定义一个resultMap,将属性名和字段名进行手动映射

        resultMap放入mapper.xml的<mapper></mapper>中 

<resultMap id="UserMapper" type="com.example.demo.model.UserInfo">
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="password" property="password"></result>
    </resultMap>
<select id="getUserById" resultMap="BaseMap">
        select * from userinfo where id=#{id}
    </select>

以下是对应关系:尽量把全部属性映射上,否则多表查询时可能会报错。

上图有个错误!!!  colum是表里面的字段名,property是实体类里的属性,写反了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值