冬雨财经 发表于 2025-4-4 10:25:34

【JavaEE进阶】MyBatis 操纵数据库(3)

https://i-blog.csdnimg.cn/direct/533901997b374f549865fecca990136c.jpeg
欢迎关注个人主页:逸狼
创造不易,可以点点赞吗
如有错误,欢迎指出~
动态SQL

动态SQL是Mybatis的强⼤特性之⼀,可以大概完成差别条件下差别的sql拼接
<if>标签

注册分为两种字段:必填字段和⾮必填字段,那如果在添加⽤⼾的时候有不确定的字段传⼊,程序应 该如何实现呢? 这个时候就需要使⽤动态标签来判定了,
<if>标签中test 属性是必须的,用于判定条件是否建立。如果条件表达式的结果为 true,则会将 <if> 标签内的 SQL 片断包罗在终极生成的 SQL 语句中;如果结果为 false,则会忽略该 SQL 片断。⽐如添加的时候性别gender为⾮必填字段,具体实现如 下:
接口
    Integer insertByCondition(UserInfo userInfo);
Mapper.xml实现: 
    <insert id="insertByCondition">
      INSERT INTO user_info (
      username,
      `password`,
      age,
      <!-- 动态判断是否添加 gender 列 -->
      <if test="gender != null">
            gender
      </if>
      )
      VALUES (
      #{username},
      #{password},
      #{age},
      <!-- 动态判断是否添加 gender 值 -->
      <if test="gender != null">
            #{gender}
      </if>
      )
    </insert> 注解方式实现(不发起) 
@Insert("<script>" +
"INSERT INTO userinfo (username,`password`,age," +
"<if test='gender!=null'>gender,</if>)" +
"VALUES(#{username},#{age}," +
"<if test='gender!=null'>#{gender},</if>)"+
"</script>")
Integer insertUserByCondition(UserInfo userInfo);
留意test中的gender,是传⼊对象中的属性,不是数据库字段


[*]Q:可不可以不进⾏判定,直接把字段设置为null呢?
[*]A:不可以,这种环境下,如果gender字段有默认值,就会设置为默认值
<trim>标签

之前的插⼊⽤⼾功能,只是有⼀个gender字段可能是选填项,如果有多个字段,⼀般思量使⽤标签结 合标签,对多个字段都采取动态⽣成的⽅式。 标签中有如部属性:

[*]prefix:表⽰整个语句块,以prefix的值作为前缀
[*]suffix:表⽰整个语句块,以suffix的值作为后缀
[*]prefixOverrides:表⽰整个语句块要去除掉的前缀
[*]suffixOverrides:表⽰整个语句块要去除掉的后缀
调整Mapper.xml的插⼊语句为:
<insert id="insertByCondition2">
    INSERT INTO user_info
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="username != null">
            username,
      </if>
      <if test="password != null">
            `password`,
      </if>
      <if test="age != null">
            age,
      </if>
      <if test="gender != null">
            gender,
      </if>
      <if test="phone != null">
            phone
      </if>
    </trim>
    VALUES
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="username != null">
            #{username},
      </if>
      <if test="password != null">
            #{password},
      </if>
      <if test="age != null">
            #{age},
      </if>
      <if test="gender != null">
            #{gender},
      </if>
      <if test="phone != null">
            #{phone}
      </if>
    </trim>
</insert> <where>标签

看下⾯这个场景,系统会根据我们的筛选条件,动态组装where条件
https://i-blog.csdnimg.cn/direct/5668d8fd716d48308530c4777846283c.png
需求:传⼊的⽤⼾对象,根据属性做where条件查询,⽤⼾对象中属性不为null的,都为查询条件.如 username为"a",则查询条件为whereusername="a"
    <select id="selectByConditoin2" resultType="com.example.demo.model.UserInfo">
      select * from user_info
      where
            <if test="gender != null">
                gender = #{gender}
            </if>
            <if test="age != null">
                and age = #{age}
            </if>
    </select> 当条件gender和age都没有时,报错如下 
https://i-blog.csdnimg.cn/direct/f0ccb11f87b04491ac985925d9a0d823.png
办理方法一
    <select id="selectByConditoin2" resultType="com.example.demo.model.UserInfo">
      select * from user_info
      where 1=1
            <if test="gender != null">
                and gender = #{gender}
            </if>
            <if test="age != null">
                and age = #{age}
            </if>
    </select> https://i-blog.csdnimg.cn/direct/5742e42ed8734041a952d01d7e2b3642.png
方法二: 使用<where>标签
只会在⼦元素有内容的环境下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或 OR 以上标签也可以使⽤ 替换,但是此种 环境下,当⼦元素都没有内容时,where关键字也会保存
    <select id="selectByConditoin" resultType="com.example.demo.model.UserInfo">
      select * from user_info
      <where>
            <if test="gender != null">
                and gender = #{gender}
            </if>
            <if test="age != null">
                and age = #{age}
            </if>
      </where>
    </select> https://i-blog.csdnimg.cn/direct/ed240d22fc8e4de88be17a705e063186.png
<set>标签

需求:根据传⼊的⽤⼾对象属性来更新⽤⼾数据,可以使⽤标签来指定动态内容. 接⼝界说:根据传⼊的⽤⼾id属性,修改其他不为null的属性
<!--    <update id="updateByCondition">-->
<!--      update user_info set-->
<!--      <trim suffixOverrides=",">-->
<!--            <if test="username!= null">-->
<!--                username = #{username},-->
<!--            </if>-->
<!--            <if test="password != null">-->
<!--                password = #{username},-->
<!--            </if>-->
<!--            <if test="gender">-->
<!--                gender = #{gender}-->
<!--            </if>-->
<!--      </trim>-->
<!--      where id = #{id}-->
<!--    </update>-->

    <update id="updateByCondition">
      update user_info
      <set>
            <if test="username!= null">
                username = #{username},
            </if>
            <if test="password != null">
                password = #{username},
            </if>
            <if test="gender">
                gender = #{gender}
            </if>
      </set>

      where id = #{id}
    </update> 动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.(⽤于update语句中) 以上标签也可以使⽤ 替换。
<foreach>标签

对集合进⾏遍历时可以使⽤该标签。标签有如部属性:

[*]collection:绑定⽅法参数中的集合,如List,Set,Map或数组对象
[*]item:遍历时的每⼀个对象
[*]open:语句块开头的字符串
[*]close:语句块结束的字符串
[*]separator:每次遍历之间间隔的字符串 需求:根据多个userid,删除⽤⼾数据
<delete id="deleteByIds">
delete from userinfo
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete> <include>标签

问题分析: • 在xml映射⽂件中设置的SQL,有时可能会存在许多重复的⽚段,此时就会存在许多冗余的代码
https://i-blog.csdnimg.cn/direct/6bdccacc46394769b296ce0c2570ef23.png
我们可以对重复的代码⽚段进⾏抽取,将其通过 标签封装到⼀个SQL⽚段,然后再通过 标签进⾏引⽤。
• :界说可重⽤的SQL⽚段
• :通过属性refid,指定包罗的SQL⽚段

<sql id="allColumn">
id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>
通过 标签在原来抽取的地⽅进⾏引⽤。操纵如下:
<select id="queryAllUser" resultMap="BaseMap">
select
<include refid="allColumn"></include>
from userinfo
</select>
5<select id="queryById" resultType="com.example.demo.model.UserInfo">
select
<include refid="allColumn"></include>
from userinfo where id= #{id}
</select>
案例演示-表⽩墙

前⾯的案例中,我们写了表⽩墙,但是⼀旦服务器重启,数据仍然会丢失. 要想数据不丢失,需要把数据存储在数据库中.接下来咱们借助MyBatis来实现数据的操纵
数据准备

DROP TABLE IF EXISTS message_info;
CREATE TABLE `message_info` (
`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
`from` VARCHAR ( 127 ) NOT NULL,
`to` VARCHAR ( 127 ) NOT NULL,
`message` VARCHAR ( 256 ) NOT NULL,
`delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now() ON UPDATE now(),
PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; 引入依赖

<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
设置MySQL账号暗码

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?
characterEncoding=utf8&useSSL=false
#连接数据库的⽤⼾名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=111111

#指定mybatis输出⽇志的位置, 输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#配置驼峰⾃动转换
mybatis.configuration.map-underscore-to-camel-case=true

# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis.mapper-locations=classpath:mapper/**Mapper.xml 后端代码

model

@Data
public class MessageInfo {
    private Integer id;
    private String from;
    private String to;
    private String message;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
} MessageInfoMapper 

package com.example.demo3.mapper;

import com.example.demo3.MessageInfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface MessageInfoMapper {
//"INSERT INTO message_info (`from`, `to`, `message`) VALUES (#{from}, #{to}, #{message})"
    @Insert("insert into message_info (`from`, `to`, `message`) values (#{from}, #{to}, #{message})")
    Integer insert(MessageInfo messageInfo);

    @Select("select * from message_info ")
    List<MessageInfo> selectAll();

}

UserService

package com.example.demo3;

import com.example.demo3.mapper.MessageInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class MessageService {

    @Autowired
    private MessageInfoMapper messageInfoMapper;
    public List<MessageInfo> selectAll(){
      return messageInfoMapper.selectAll();
    }

    public void insertMessage(MessageInfo messageInfo) {
      messageInfoMapper.insert(messageInfo);
    }
}
UserController

package com.example.demo3;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/message")
public class MessageController {

//    List<MessageInfo> messageInfos = new ArrayList<>();
    @Autowired
    private MessageService messageService;

    @RequestMapping(value = "/getList")
    public List<MessageInfo> getList(){
      return messageService.selectAll();
    }

    @RequestMapping(value = "/publish", produces = "application/json")
    public String publish(@RequestBody MessageInfo messageInfo){
      if(StringUtils.hasLength(messageInfo.getMessage())
      && StringUtils.hasLength(messageInfo.getFrom())
      && StringUtils.hasLength(messageInfo.getTo())){
//            messageInfos.add(messageInfo);
//            System.out.println(messageInfo);
            messageService.insertMessage(messageInfo);
            return "{\"ok\": 1}";
      }
      return "{\"ok\": 0}";
    }
}
测试结果 

欣赏器访问的结果 

https://i-blog.csdnimg.cn/direct/dd1db50bf9f64b2c87e8c52fbbbbff81.png
输⼊留⾔信息,点击提交,发现⻚⾯列表显⽰新的数据,并且数据库中也添加了⼀条记载. 
数据库中存储的结果 

https://i-blog.csdnimg.cn/direct/c3fa9f6fdc9c41a3b7c074dbb6bbd02e.png 重启服务,⻚⾯显⽰不变.

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【JavaEE进阶】MyBatis 操纵数据库(3)