Mybatis

本文介绍了如何在SpringBoot项目中使用Mybatis进行数据库操作,包括引入依赖、配置数据库、编写Mapper接口、注解驱动的SQL编写、测试类的使用、日志配置、动态SQL和参数映射等。
摘要由CSDN通过智能技术生成

创建Mybatis项目

MyBatis的写法

1.xml
2.注解
 

1.引入Mybatis依赖,引入对应数据库的依赖,比如mysql.

2.配置数据库相关信息

spring:
  datasource:
   url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
   username: root
   password: 1234
   driver-class-name: com.mysql.cj.jdbc.Driver


3.定义Java对象

package com.example.demo;

import java.util.Date;

public class UserInfo {

    private Integer id ;
    private String username;
    private String password ;
    private Integer age;
    private Integer gender;
    private String phono;
    private Integer delete_flag;
    private Date createTime ;
}


4.写实现
实现这里的@select注解是sql语句,其下面是对应方法声明。@Mapper注解, mybatis就会告诉Spring,把对象交给Spring管理。

package com.example.demo;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.web.bind.annotation.Mapping;

import java.util.List;

@Mapper
public interface UserInfoMapper {

    @Select("select * from userinfo")
    List<UserInfo> selectAll();
}

在数据库中使用删除时分为:逻辑删除和物理删除
逻辑删除:指从逻辑上进行数据删除。物理删除:从硬盘上进行数据删除delete。二者的区分就是是否保存数据,现在数据非常宝贵,可以通过日常数据得知每个人的偏好和各种信息,所以现在一般都是采用逻辑删除来进行保存信息。

写测试类

右键生成中有测试直接选中

将这些都选中就会出现如下

@Slf4j//日志框架
@SpringBootTest//必需写上将Spring容器中的数据注入其中
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @BeforeEach//结果出现前打印
    void setUp() {
        log.info("setUP");
    }

    @AfterEach//结果出现后打印
    void tearDown() {
        log.info("setUP");

    }

    @Test
    void selectAll(){

        List<UserInfo> list =userInfoMapper.selectAll();
        log.info(list.toString()) ;
    }
}

在运行时,报这个错误时是有可能org.springframework.beans.factory.UnsatisfiedDependencyException

在启动类上面注解的后面加了(exclude = {DataSourceAutoConfiguration.class}),其意思是Spring Boot将不会自动配置数据源JPA存储库相关的bean。

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

去掉之后正常运行

Mybaties的日志打印


mybatis:
  configuration: #配置打印MyBatis日志
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

将会详细打印出数据库查询的运行轨迹

根据参数来进行查询结果

虽然如果只有一个参数,SQL的名称可以为任意的,但是还是将名称改为与其对应的,代码可读性高,以后也比较好进行修改。
 

@Select("select * from userinfo where  id =#{id}")
    UserInfo selectOne(Integer id);




//test
@Test
    void selectOne() {
        UserInfo userInfo = userInfoMapper.selectOne(1);
        log.info(userInfo.toString());

    }

查询结果

同时也可以将参数进行重命名来进行使用

   @Select("select * from userinfo where  id =#{userId}")
    UserInfo selectOne2(@Param("userId") Integer id);

将参数进行重命名的目的是

  1. 语义化命名: 参数名 userId 更直观地表示了参数的含义,明确了该参数表示的是用户的 ID。
  2. 避免歧义: 当方法参数较多时,可能存在多个 id 参数,此时通过重命名可以避免歧义,明确是哪个参数代表用户的 ID。
  3. 可维护性: 如果后续需要修改参数名,只需要修改 @Param 注解中的值,而不需要修改 SQL 查询语句中的参数名,降低了修改的风险

插入数据

  @Insert("insert into userinfo (username,password,age,gender,phone)"+
            "values (#{username},#{password},#{age},#{gender},#{phone})")
    Integer insert(UserInfo userInfo);

//test
 @Test
    void insert() {
        UserInfo userInfo = new UserInfo();
       userInfo.setUsername("sadada");
       userInfo.setPassword("32324");
       userInfo.setAge(2);
       userInfo.setGender(1);
       userInfo.setPhone("213123123");
       Integer result = userInfoMapper.insert(userInfo);
       log.info("insert",result);
    }

结果

查询数据库中自增的数据

这个Op注解设置为true就是将自增数据的读取权限给打开,然后你就可以进行读取

sql语句太长换行加上”+“连进行连接

@Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into userinfo (username,password,age,gender,phone)"+
            "values (#{username},#{password},#{age},#{gender},#{phone})")
    Integer insert(UserInfo userInfo);


//test
@Test
    void insert() {
        UserInfo userInfo = new UserInfo();
       userInfo.setUsername("ewqrwe");
       userInfo.setPassword("ewrwe");
       userInfo.setAge(1);
       userInfo.setGender(1);
       userInfo.setPhone("213123123");
       Integer result = userInfoMapper.insert(userInfo);
       log.info("insert,结果:{} ,自增ID:{}",result,userInfo.getId());//必修要使用{}才能捕获输出的值
    }

不设置就会产生下面

参数为对象时,对参数进行重命名

并且重命名时,必修在参数前加上重命名的名称加上.否则不能进行识别,会报错

 @Insert("insert into userinfo (username,password,age,gender,phone)"+
            "values (#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender},#{userInfo.phone})")
    Integer insert(@Param("userInfo") UserInfo userInfo);

删除数据

  @Delete("delete from userinfo where id =#{id}")
    Integer delete(Integer id);


    @Test
    void delete() {
        UserInfo userInfo = new UserInfo();
        Integer result = userInfoMapper.delete(16);
        log.info("delete,{}",result);
    }

更改数据

 @Insert("insert into userinfo (username,password,age,gender,phone)"+
            "values (#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender},#{userInfo.phone})")
    Integer insert(@Param("userInfo") UserInfo userInfo);


//test
@Test
    void update() {
        UserInfo userInfo = new UserInfo();
        userInfo.setAge(55);
        userInfo.setId(10);
        Integer result = userInfoMapper.update(userInfo);
        log.info("update  {}",result);
    }

通过结果映射进行查询

结果映射
Mybatis 会自动的根据数据库的字段名和Java对象的属性名,进行映射如果名称一样.就讲行赋值

相同就进行了赋值,不同就置为空。

1.直接使用配置来进行自动转化

将createTime转化为create_time类型


mybatis:
  configuration: #配置打印MyBatis日志
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
   map-underscore-to-camel-case: true #配置驼峰自动转换


2.使用@Results注解

左边是数据库,右边是java对象的属性。并且其还能进行复用,在想复用的的方法上加上

@ResultMap(value = "BaseMap")

  @Results(id= "BaseMap",value = {
            @Result(column = "delete_flag",property = "deleteFlag")
    })
    @Select("select * from userinfo")
    List<UserInfo> selectAll2(); 

    //复用
    @ResultMap(value ="BaseMap")
    @Select("select * from userinfo;")
    List<UserInfo> selectAll();

XML方式

1.先配置数据库

2.指明xml的路径

mybatis:
#  configuration: #配置打印MyBatis日志
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#    map-underscore-to-camel-case: true #配置驼峰自动转换

  mapper-locations:
    classpath:mapper/**Mapper.xml

classpath后面对应的是Mapper.xml放在哪里并且Mapper.xml这个文件前面是什么无所谓,只要后面这几个是Mapper.xml就可以。

3.写XML的实现

namespace后面写的要实现哪个接口以及要写接口的全限定类名。id写的是实现的方法名,resultType则是返回的类型,返回的是对象,或者list, 此处定义的都是返回的数据的类型

<?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.mapper.UserInfoXMLMapper">

<select id="selectALL" resultType="com.example.demo.UserInfo">
      select * from userinfo
</select>
</mapper>



//所在的类的方法

@Mapper
public interface UserInfoXMLMapper {
    List<UserInfo> selectALL();
}

如果下面报错

Invalid bound statement (not found):com.bite.demo.mapper.UserInfoXNLNapper.selectAll

可能原因
1.xml和接口定义的方法名称不一致    2.mapper的路径配置和xml的路径不一样        3.xml namespace写错了

曾删改和注解类似

  Integer insert(UserInfo userInfo);
//XML
     <insert id="insert">
            insert into userinfo (username,password,age,gender,phone)
            values(#{username},#{password},#{age},#{gender},#{phone})
      </insert>
//test

  @Test
    void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("ewqrwe");
        userInfo.setPassword("ewrwe");
        userInfo.setAge(1);
        userInfo.setGender(1);
        userInfo.setPhone("213123123");
        Integer result = userInfoXMLMapper.insert(userInfo);
        log.info("result ,{}",result);
    }

   

    Integer insert2(@Param("userInfo") UserInfo userInfo);
//XML
    <insert id="insert2" useGeneratedKeys="true" keyProperty="id">
            iinsert into userinfo (username,password,age,gender,phone)
            values(#{userInfo.username},#{userInfo.password}
            ,#{userInfo.age},#{userInfo.gender},#{userInfo.phone})
    </insert>
//test

 @Test
    void insert2() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("ewqrwe");
        userInfo.setPassword("ewrwe");
        userInfo.setAge(1);
        userInfo.setGender(1);
        userInfo.setPhone("213123123");
        Integer result = userInfoXMLMapper.insert(userInfo);
        log.info("result ,{}",result);
    }


    Integer delete(Integer id);

//XML
     <delete id="delete">
            delete from userinfo where id =#{id}
      </delete>

//test

@Test
    void delete() {

        UserInfo userInfo = new UserInfo();
        Integer result = userInfoXMLMapper.delete(11);
        log.info("delete,{}",result);
    }

  

    Integer update(UserInfo userInfo);
//Xml
      <update id="update">
            update userinfo set gender =#{gender}
            where id =#{id}
      </update>
//test
  @Test
    void update() {
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(2);
        userInfo.setId(2);
        Integer result = userInfoXMLMapper.update(userInfo);
        log.info("update,{}",result);
    }

动态SQL的使用:根据需求,动态的拼接sql

XML方式的明显可读性很高

如果性别不为空不为空都不可读,if就是用来判断的条件

//注解方式  
@Insert("<script>" +
                   "INSERT INTO userinfo (username,`password`,age," +
                   "<if test='gender!=null'>gender,</if>" +
                   "phone)" +
                   "VALUES(#{username},#{age}," +
                   "<if test='gender!=null'>#{gender},</if>" +
                   "#{phone})"+
                   "</script>")
    Integer insert2(UserInfo userInfo);


//XML
 <insert id="insert3">
      INSERT INTO userinfo (
      username,
      `password`,
      age,
      <if test="gender != null">
            gender,
      </if>
      phone)
      VALUES (
      #{username},
      #{age},
      <if test="gender != null">
            #{gender}
      </if>
      #{phone})
      </insert>


<trim>标签帮助我们去除多余的字符

<trim>

prefix0verrides去除trim标签代码块指定的字符

prefix在trim标签代码块最前面添加指定的字符
suffix在trim标签代码块最后面添加指定的字符
suffix0verrides去除trim标签代码块最后面指定的字符
示例

 <trim suffixOverrides="," prefix="(" suffix=")">
            <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>

XML中的插入

    <insert id="insert3">
      INSERT INTO userinfo
      <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>

基于prefix配置,开始部分加上( 。

基于suffix配置,结束部分加上)
多个组织的语句都以,结尾,在最后拼接好的字符串还会以,结尾,会基于suffixOverrides配置去掉最后一个,
注意<if test="username !=null">中的username是传入对象的属性

<where>标签

如果查询条件都为空, where标签会自动去除where关键

<select id="selectAll" resultType="com.example.demo.model.UserInfo">
      select id, username, age, gender, phone, delete_flag, create_time,
      update_time
      from userinfo
      <where>
      <if test="age != null">
            and age = #{age}
      </if>
      <if test="gender != null">
            and gender = #{gender}
      </if>
            <if test="deleteFlag != null">
                  and delete_flag = #{deleteFlag}
            </if>
      </where>
      </select>

where标签只会在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或 OR

<set>标签

 <update id="update">
      update userinfo
      <set>
      <if test="username != null">
            username = #{username},
      </if>
            <if test="age != null">
                  age = #{age},
            </if>
            <if test="deleteFlag != null">
                  delete_flag = #{deleteFlag},
            </if>
      </set>
            where id = #{id}
      </update>

set标签动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.

<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>标签

使用一些重复的sql时,使用<include>标签来进行重复使用

//可以重复使用的
<sql id="allColumn">
 id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>



//include标签
<select id="queryAllUser" resultMap="BaseMap">
 select
 <include refid="allColumn"></include>
 from userinfo
</select>
<select id="queryById" resultType="com.example.demo.model.UserInfo">
 select
 <include refid="allColumn"></include>
 from userinfo where id= #{id}
</select>


 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值