目录

【快速入门】MyBatis

一.基础操作

1.准备工作

1)引入依赖

一个是mysql驱动包,一个是mybatis的依赖包:

XML 复制代码
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.4</version>
</dependency>

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

如果创建项目后,项目中自带着就不用引入了。

2)配置文件

数据库连接配置:

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

上面的username和password要根据自己的数据库进行修改。

这个是我们要用的数据库的名字,也要根据自己的数据库进行修改。

如果使用mysql是5.x之前 的使用的是 com.mysql.jdbc.Driver ,如果是大于5.x 使用的是 com.mysql.cj.jdbc.Driver

打印日志配置:

复制代码
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2.查询(select)

对于查询,使用 @Select这个标签即可完成。

复制代码
@Select("SQL语句")

举个例子,我们想要查询 user_info 这个表:

java 复制代码
@Select("select * from user_info;")
List<UserInfo> selectAll();

@Select("select * from user_info where id=3;")
List<UserInfo> selectById();

此时,selectAll()这个方法就具有了查询 user_info 这个表的功能。

那如果我们想要指定参数,那么要使用 #{参数} :

java 复制代码
@Select("select * from user_info where id=#{id};")
List<UserInfo> selectById(Integer id);

@Select("select * from user_info where id=#{id} and username = #{username};")
List<UserInfo> selectByIdAndName(String username,Integer id);

我们可以使用 @Param 这个注解对参数进行重命名,但是要保证重命名后的参数必须是重命名:

java 复制代码
@Select("select * from user_info where id=#{userId};")
List<UserInfo> selectByIdAndName1(@Param("userId") Integer id);

这里要注意一件事,只有数据库的字段与Java中的对象属性相同时才能进行赋值,那如果不同怎么办呢?

1)别名查询

从SQL语句入手,我们将字段与属性名不同的起一个别名

java 复制代码
@Select("select user_name as username from user_info ;")
List<UserInfo> selectAll1();

这样,即使数据库字段是user_name也会成功查询。

2)结果映射

使用 @Results 注解

java 复制代码
@Results(id = "BaseMap",value = {
        @Result(column = "user_name",property = "userName"),
        @Result(column = "create_time",property = "createTime"),
        @Result(column = "update_time",property = "updateTime")
})
@Select("select * from user_info;")
List<UserInfo> selectAll();

3)驼峰自动转换

数据库使用蛇形命名法,Java中使用驼峰命名法,通过配置可以两种命名进行自动映射,但是要注意,一定要遵从上述的命名方法,不遵从也不好使。

复制代码
mybatis:
  configuration: 
    map-underscore-to-camel-case: true #配置驼峰⾃动转换

3.插入(insert)

插入操作使用 @Insert注解,用法与查询的大差不差,重复的内容就不过多介绍了:

java 复制代码
@Insert("insert into user_info(username,`password`) values(#{username},#{password});")
Integer insertUser(UserInfo userInfo);

@Insert("insert into user_info(username,`password`,age) values(#{userInfo.username},#{userInfo.password},#{userInfo.age});")
Integer insertUser(@Param("userInfo") UserInfo userInf);

insertUser返回的Integer是收影响的行数。

这里要注意重命名那里要使用 参数.属性来获取。

如果我们想要获取主键,执行完SQL语句后,使用userInf.getId()是获取不到的。要使用Options注解:

java 复制代码
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into user_info(username,`password`,age) values(#{username},#{password},#{age});")
Integer insertUser(UserInfo userInfo);

4.删除(delete)

这个注解是什么应该不难猜了,@Delete

java 复制代码
@Delete("delete from user_info where id=#{id}")
Integer deleteUser(Integer id);

5.更新(update)

注解 @Update,其他与上面的注解都一样。

java 复制代码
@Update("update user_info set phone=#{phone} where id=#{id}")
Integer updateUser(Integer phone,Integer id);

二.XML配置文件

1.准备工作

1)配置文件

复制代码
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml

注意后面的 **Mapper ,这个要根据实际情况写,这个的意思是以 Mapper 为后缀。如果我们写的xml文件的后缀不是 Mapper ,那么要改成与xml文件名相同。

2)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="***********">

 </mapper>

上面******这些要填的是实现Mapper的类的路径,即全包名+类名

2.查询(select)

接口中的方法:

java 复制代码
List<UserInfo> selectAll();
List<UserInfo> selectById(Integer id);

在xml文件中写:

XML 复制代码
<select id="selectAll" resultType="com.springdemo.model.UserInfo">
    select * from user_info;
</select>
<select id="selectById" resultType="com.springdemo.model.UserInfo">
    select * from user_info where id = #{id};
</select>

id是与对应接口的方法的名称是一样的,resultType是返回的数据类型。

使用xml文件的方法仍然存在数据库字段与对象属性不同的无法赋值的情况,处理方法与注解的一样,都是三种,其中别名查询和配置文件这两个处理方法相同,这里说一下不同的结果映射。

XML 复制代码
<resultMap id="BaseMap" type="com.springdemo.model.UserInfo">
    <id column="id" property="id"></id>
    <result column="create_time" property="createTime"></result>
    <result column="update_time" property="updateTime"></result>
</resultMap>
<select id="selectAll" resultMap="BaseMap">
    select * from user_info;
</select>

在resultMap结构中,id是主键,result中的column是数据库字段名,property是对象属性名。

3.插入(insert)

xml文件:

XML 复制代码
<insert id="insertUser">
    insert into user_info(username,`password`,age) values(#{username},#{password},#{age});
</insert>

返回主键:

XML 复制代码
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    insert into user_info(username,`password`,age) values(#{username},#{password},#{age});
</insert>

从这里我们也能发现:其实这些代码都是重复的,就换个词,包括重命名啥的,本质上没有变化,下面只是简单的给出xml文件代码。

4.删除(delete)

XML 复制代码
<delete id="deleteUser">
    delete from user_info where id=#{id};
</delete>

5.更新(update)

XML 复制代码
<update id="updateUser">
    update user_info set phone=#{phone} where id=#{id};
</update>

三.${}与#{}

1.区别

前面一直使用的是#{},那${}是什么。

在实际使用上,我们仅通过看是看不出什么区别的,用是一样用,但是得到的结果是不同的。

java 复制代码
@Select("select * from user_info where username=#{name}")
//@Select("select * from user_info where username=${name}")
List<UserInfo> selectByName(String name);

分别运行上面的两个注解,得到下面的运行结果:

#{}的正常:

${}的报错了:

报错提示是SQL写错了。

${}写的SQL语句,我们写的参数是直接拼接上的,username直接等于了lisi,lisi应该是一个字符串,不应该直接拼上去,要加上''。#{}是通过占位符的方法

我们这样修改上面的注解就可以了:

java 复制代码
@Select("select * from user_info where username='${name}'")
List<UserInfo> selectByName(String name);

但是这又引出了一个新的问题,SQL注入。

由于使用是直接拼接上的,那么完全可以实现SQL注入,因此使用{}是直接拼接上的,那么完全可以实现SQL注入,因此使用{}的时候就要注意SQL注入问题。

所以,相对${},#{}可谓是优势满满:

1)性能更高,#{}是预编译SQL,其在编译一次后会缓存,下次再次执行的时候就不用编译了;

2)没有SQL注入,更加安全;

那${}真的一无是处吗?存在即合理,要是一点用没有早删了。

2.${}应用

举一个例子,在某些场景下,我们需要对某一数据进行排序查询。先简单写一个查询排序:

sql 复制代码
select * from standings order by chinese DESC

desc是降序,asc是升序。

从上面的例子可以看到,desc是没加 ' ' 的。如果我们使用#{},势必会加上 ' ' 。这个时候我们就使用${},可以通过直接拼接来实现。但是也要注意SQL注入问题。

再举一个例子,我们要对表进行模糊匹配查询,简单写一个模糊匹配查询:

java 复制代码
@Select("select name from standings where name like '${name}%'")

上面的?可以填入任意参数,如果我们使用#{},那么就无法将%给包进去,使用${}就可以。但是这个也有SQL注入问题,我们在实际开发中使用的是mysql内置函数concat来处理:

java 复制代码
@Select("select name from standings where name like concat(${name},'%')")

还有一个场景是我们写的SQL要传入参数名,这个时候也要使用${},不能使用#{}。

四.动态SQL

在某些场景,我们传入的字段不是固定的。比如在用户填写个人信息的时候,有一些是必填的,有一些呢可以默认,有一些可以不填。我们在写代码的时候难道要给每一种情况都写一个方法吗?当然不是,这其实就是动态SQL干的事了。

动态SQL可以动态的完成SQL拼接。

1.<if>标签

这个标签就可以动态的填入那些不确定的字段。这个是写在XML文件中的:

XML 复制代码
<insert id="insertUser">
    insert into user_info(
    username,
    `password`,
    <if test="gender!=null">
        gender,
    </if>
    age)
    values(
    #{username},
    #{password},
    <if test="gender!=null">
        #{gender},
    </if>
    #{age})
</insert>

那用注解的方法呢?

用注解写的比较难看,具体写法就是使用**<script></script>**将上面写的XML语句写在标签中。

下面的各个命名一定要分清,属性名一定要与我们定义的类中的名相同,别乱写,字段名就是数据库中的数据名称。

2.<trim>标签

有这么一种情况,我们要将最前面的一个参数设成不确定参数。如果第一个参数不填,那么就会出现错误,即多出一个 ,

XML 复制代码
<insert id="insertUser">
    insert into user_info(
    <if test="gender!=null">
        gender
    </if>                      
    ,username
    ,`password`
    ,age)
    values(
    <if test="gender!=null">
        #{gender}
    </if>       
    ,#{username}
    ,#{password}
    ,#{age})
</insert>

面对这种问题,我们可以使用<trim>标签来添加和去除前后缀:

XML 复制代码
<insert id="insertUser">
    insert into user_info
    <trim prefix="(" suffix=")" prefixOverrides=",">
        <if test="gender!=null">
            gender
        </if>
        ,username
        ,`password`
        ,age
    </trim>    
        values
    <trim prefix="(" suffix=")" prefixOverrides=",">
        <if test="gender!=null">
            #{gender}
        </if>
        ,#{username}
        ,#{password}
        ,#{age}
    </trim>
</insert>

|-----------------|--------------------|
| prefix | 整个语句块以prefix的值作为前缀 |
| suffix | 整个语句块以suffix的值作为后缀 |
| prefixOverrides | 整个语句块要去除的前缀 |
| suffixOverrides | 整个语句块要去除的后缀 |

3.<where>标签

这种用于在使用where的时候,我们要动态的插入where中的条件:

XML 复制代码
<select id="selectByIdAndName" resultType="com.springdemo.model.UserInfo">
    select * from user_info
    <where>
        <if test="id!=null">
            and id=#{id}
        </if>
        <if test="username!=null">
            and username = #{username}
        </if>
    </where>
</select>

where标签会自动帮我们去除掉多余的 and 或 or

4.<set>标签

这种用于更新(update)数据的时候,我们要动态的传入数据:

XML 复制代码
<update id="updateUser">
    update user_info
    <set>
        <if test="phone!=null">
            phone=#{phone},
        </if>
        <if test="gender!=null">
            gender=#{gender},
        </if>
    </set>>
    where id=#{id};
</update>

set标签会自动去除掉多余的,

5.<foreach>标签

这种用于遍历集合。比如我们想要根据一个List集合去删除对应id的用户,我们可以使用foreach标签去遍历每一个id:

XML 复制代码
<delete id="deleteUser">
    delete from user_info 
    where id in 
    <foreach collection="idList" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>

|------------|--------------|
| collection | 绑定方法参数中的集合 |
| item | 遍历时的每一个对象 |
| open | 语句块开头的字符串 |
| close | 语句块结束的字符串 |
| separator | 每次遍历之间间隔的字符串 |

6.<include>标签

主要用于处理冗余重复的片段。

我们使用<sql>标签定义可重定向的sql片段,<include>标签来获取<sql>中的片段。

XML 复制代码
<sql id="allColumn">
    id,name,age
</sql>>
<select id="selectById" resultType="com.gdut.springdemo08.model.UserInfo">
    select
    <include refid="allColumn"></include>
    from user_info where id = #{id};
</select>
本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
forestsea2 分钟前
Java 8 Stream API:传统实现和流式编程的范式对比
java·开发语言
tan_jianhui9 分钟前
用maven生成springboot多模块项目
java·spring boot·maven
珹洺11 分钟前
计算机网络:(二)计算机网络在我国发展与网络类别与性能 (附带图谱更好对比理解)
运维·服务器·网络·数据库·后端·计算机网络
Pandaconda11 分钟前
【后端开发面试题】每日 3 题(十三)
redis·分布式·后端·面试·kafka·后端开发·缓存消息队列
多多*16 分钟前
Spring设计模式 八股速记 高层模块底层模块 依赖倒置原则 开闭原则 接口隔离原则
java·开发语言·数据库·macos·github·objective-c·cocoa
ivygeek18 分钟前
MCP:基于Java SDK 实现一个 Mcp Server
后端·mcp
这里有鱼汤22 分钟前
解决Python路径问题:为什么你应该用 pathlib 替代 os.path
后端·python
Victor35623 分钟前
Dubbo(1)什么是Dubbo?
后端
程序员清风23 分钟前
谈谈Select For Update的实现原理?
数据库·后端·面试
tangweiguo0305198727 分钟前
Android 高版本兼容的原生定位工具类封装(支持 Android 5.0 到 Android 14)
android·java·location