MyBatis 查询数据库

x33g5p2x  于2022-06-08 转载在 其他  
字(13.4k)|赞(0)|评价(0)|浏览(424)

1. 什么是MyBatis

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
 
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
 
MyBatis 可以通过简单的 XML注解 来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

用一句简单的话来概述: MyBatis 是更简单完成程序和数据库交互的工具MyBatis 是更简单的操作和读取数据库工具

2. 配置 MyBatis 的开发环境

2.1 准备工作, 创建数据库和表

create database if not exists MyBlogSystem;

use MyBlogSystem;

drop table if exists blog;

-- 创建一个博客表
create table blog (
    blogId int primary key auto_increment,
    title varchar(1024),
    content mediumtext,
    postTime datetime,
    userId int
);

drop table if exists user;

-- 创建一个用户信息表
create table user (
    userId int primary key auto_increment,
    username varchar(128) unique,
    password varchar(128)
);

2.2 添加 MyBatis 依赖

<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.2.2</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

2.3 配置连接字符串和 MyBatis

2.3.1 配置数据库连接信息

spring.datasource.url=jdbc:mysql://localhost:3306/MyBlogSystem?characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

2.3.2 配置 MyBatis 中的 XML 路径

配置 mybatis 的文件路径, 在 resources/mapper 创建所有表的xml文件

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

这里必须要一样

2.4 添加代码

2.4.1 添加实体类

添加用户的实体类

@Getter
@Setter
@ToString
public class User {
    public int userId;
    public String username;
    public String password;
}

2.4.2 添加 mapper 接口

@Mapper
public interface UserMapper {
    List<User> getAll();
}

2.4.3 添加 UserMapper.xml

固定的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.mapper.UserMapper">
    
</mapper>

这里的 UserMapper.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.mapper.UserMapper">
    <select id="getAll" resultType="com.example.demo.model.User">
        select * from user;
    </select>
</mapper>

2.4.4 添加 Service

@Service
public class UserService {

    // 记得要注入
    @Resource
    private UserMapper userMapper;

    public List<User> getAll() {
        return userMapper.getAll();
    }
}

2.4.5 添加 Controller

// 这里的 @RestController 相当于 @Controller + @ResponseBody
@RestController
@RequestMapping("/user")
public class UserController3 {
    @Autowired
    private UserService userService;
    
    @RequestMapping("/getall")
    public List<User> getAll() {
        return userService.getAll();
    }
}

2.4.6 测试代码

2.5 注意事项

  1. 注意配置文件中的mapper配置和mapper文件夹的对应

  2. UserMapper.xml 这里需要一些路径对应, 以及id格式对应 , 这里的resultType是返回的类型.

  1. 按照业务规定流程写代码

3. MyBatis 的增删改查操作.

3.1 增加操作

步骤:

  • 添加 实体类(这里有了就不需要添加了)
  • 添加 controller
  • 添加 service
  • 添加 mapper 接口
  • 添加 xml

① 添加 controller 实现代码

@RestController
@RequestMapping("/user")
public class UserController3 {
    @Autowired
    private UserService userService;

    @RequestMapping("/insert")
    public Integer insert(User user) {
        return userService.insert(user);
    }
}

② 添加 service 实现代码

@Service
public class UserService {
    // 记得要注入
    @Resource
    private UserMapper userMapper;

    public Integer insert(User user) {
        return userMapper.insert();
    }
}

③ 添加 mapper 接口

@Mapper
public interface UserMapper {
    Integer insert();
}

④ 添加 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.mapper.UserMapper">
    <insert id="insert">
        insert into user values (null, #{username},#{password});
    </insert>
</mapper>

⑤ 测试代码

3.2 查找操作

步骤:

  • 添加 实体类(这里有了就不需要添加了)
  • 添加 controller
  • 添加 service
  • 添加 mapper 接口
  • 添加 xml

① 添加 controller

@RequestMapping("/getall")
    public List<User> getAll() {
        return userService.getAll();
    }

② 添加 service

@RequestMapping("/getall")
    public List<User> getAll() {
        return userService.getAll();
    }

③ 添加 mapper 接口

public List<User> getAll() {
        return userMapper.getAll();
    }

④ 添加 xml

<select id="getAll" resultType="com.example.demo.model.User">
        select * from user;
    </select>

⑤ 测试代码

3.3 修改操作

步骤:

  • 添加 实体类(这里有了就不需要添加了)
  • 添加 controller
  • 添加 service
  • 添加 mapper 接口
  • 添加 xml

① 添加controller

@RequestMapping("/update")
    public Integer update(Integer userId, String password) {
        return userService.update(userId,password);
    }

② 添加 service

public Integer update(Integer userId, String password) {
        return userMapper.update(userId,password);
    }

③ 添加 mapper 接口

Integer update(Integer userId, String password);

④ 添加 xml

<update id="update">
        update user set password=#{password} where userId=#{userId}
    </update>

⑤ 测试代码

3.4 删除操作

步骤:

  • 添加 实体类(这里有了就不需要添加了)
  • 添加 controller
  • 添加 service
  • 添加 mapper 接口
  • 添加 xml

① 添加 controller

@RequestMapping("/delete")
    public Integer delete(Integer userId) {
        return userService.delete(userId);
    }

② 3.4.2 添加 service

public Integer delete(Integer userId) {
        return userMapper.delete(userId);
    }

③ 添加 mapper 接口

Integer delete(Integer userId);

④ 添加 xml

<delete id="delete">
        delete from user where userId=#{userId}
    </delete>

⑤ 测试代码

4. MyBatis 的进阶操作

4.1 返回自增id

这里用增加操作来进行演示

4.1.1 添加 controller 实现代码

@RequestMapping("/insert2")
    public Integer insert2(User user) {
        if (user == null || user.getUsername() == null
                || user.getPassword() == null
                || user.getUsername().equals("")
                || user.getPassword().equals("")
        ) { // 非法参数
            return 0;
        }
        userService.insert2(user);
        return user.getUserId();
    }

4.1.2 添加 service 实现代码

public void insert2(User user) {
        userMapper.insert2(user);
    }

4.1.3 添加 mapper 接口

void insert2(User user);

4.1.4 添加 xml

注意: 如果要返回自增id, 就不能像普通增加那样写xml

正确写法:

<insert id="insert2" useGeneratedKeys="true" keyProperty="userId" keyColumn="userId">
        insert into user values (null,#{username}, #{password});
    </insert>
  • useGeneratedKeys: 这个会取出数据库内部生成的主键, 默认值是false
  • keyColumn: 设置生成键值在表中的列名, 在某些数据库中, 当主键列不是表中第一列的时候, 是必须设置的.如果生成列不止一个, 可以用逗号分隔多个属性名称
  • keyProperty: 指定能够唯一标识对象的属性, 默认值: 未设置(unset), .如果生成列不止一个, 可以用逗号分隔多个属性名称

4.1.5 测试代码

4.2 一对一的表映射

4.2.1 xml中具体的实现

一对一的表映射要使用 <association> 标签, 具体实现

<resultMap id="baseMap" type="com.example.demo.model.User">
        <!-- 主键映射 -->
        <id column="userId" property="userId"></id>
        <!-- 普通映射 -->
        <result column="username" property="username"></result>
        <result column="password" property="password"></result>
    </resultMap>
    <resultMap id="BaseMap" type="com.example.demo.model.Blog">
        <id column="blogId" property="blogId"></id>
        <result column="title" property="title"></result>
        <result column="content" property="content"></result>
        <result column="postTime" property="postTime"></result>
        <result column="userId" property="userId"></result>
        <association property="user"
                     resultMap="com.example.demo.mapper.UserMapper.baseMap"
                     columnPrefix="u_">
        </association>
    </resultMap>

    <select id="getAll" resultMap="BaseMap">
        select b.*,u.userId u_userId,u.username u_username,u.password u_password from blog b left join user u on u.userId=b.userId
    </select>

注意事项:

  • property 属性: 指定 Blog 表中对应的属性名, 与实体类一致, 这里是user
  • resultMap 属性: 指定关联的结果集映射, 将基于该映射配置来组织用户数据
  • columnPrefix 属性: 绑定一对一对象时, 多表前缀, 作用防止多张表出现相同字段查询的问题

4.2.2 Blog 实体类

@Data
public class Blog {
    public int blogId;
    public String title;
    public String content;
    public Timestamp postTime;
    public int userId;
    public User user;
}

4.2.3 添加 controll

@RequestMapping("/getall")
    public List<Blog> getAll() {
        return userService.getAll();
    }

4.2.4 添加 service

public List<Blog> getAll() {
        return userMapper.getAll();
    }

4.2.5 添加 mapper

List<Blog> getAll();

4.2.6 测试运行

4.3 一对多的表映射

4.3.1 xml中具体的实现

一对多使用 <collection> 标签, 用法和 <association>相同

<resultMap id="BaseMap2" type="com.example.demo.model.Blog">
        <id column="blogId" property="blogId"></id>
        <result column="title" property="title"></result>
        <result column="content" property="content"></result>
        <result column="postTime" property="postTime"></result>
        <result column="userId" property="userId"></result>
        <collection property="user"
                    resultMap="com.example.demo.mapper.UserMapper.baseMap"
                    columnPrefix="u_">
        </collection>
    </resultMap>
    <select id="getUserById" resultMap="BaseMap2">
        select b.*,u.username u_username,u.userId u_userId,u.password u_password from blog b left join user u on b.userId=u.userId where u.userId=#{userId}
    </select>

4.3.2 添加 controller

@RequestMapping("/getUserById")
    public List<Blog> getUserById(Integer userId) {
        return userService.getUserById(userId);
    }

4.3.3 添加 service

public List<Blog> getUserById(Integer userId) {
        return userMapper.getUserById(userId);
    }

4.3.4 添加 mapper接口

List<Blog> getUserById(Integer userId);

4.3.5 测试运行

5. MyBatis 的一些注意事项

5.1 参数占位符 #{} 和 ${}

  • #{} : 预编译处理
  • ${} : 字符直接替换

编译预处理: MyBatis 在处理 #{} 时, 会将SQL 中的 #{} 替换为 ? 号, 使用 PreparedStatementset 方法来赋值.

字符直接替换: MyBatis 在处理 ${} 时, 就是把 ${} 替换成变量的值.(缺点SQL注入)

注意: 当使用 #{} 的时候, 传递值为 String则会加单引号. 使用${}的时候, 就不会加单引号

5.1.1 ${} 的优点

在对一些商品进行排序的时候, 使用${}就可以, 而使用#{}就不行

<select id="getall2" resultType="com.example.demo.model.User">
        select * from user order by userId ${sort};
    </select>

5.2 SQL 注入问题

<select id="getAll3" resultType="com.example.demo.model.User">
        select * from user where username= '${username}' and password='${password}'
    </select>

当注入 'or 1='1 时, 所有的信息就暴露了

需要用户传递的就尽量使用 #{}, 程序员自己传递的就可以使用 ${}

5.3 like 查询

like 使用 #{} 会报错
例如一段sql代码
select * from user where username like '%#{username}%';
username=admin 相当于
select * from user where username like '%'admin'%'

这里也不能直接使用 ${}.

可以使用mysql内置函数 concat() 来处理

<select id="findLike" resultType="com.example.demo.model.User">
        select * from user where username like concat('%',#{username},'%')
    </select>

5.4 实体类中的字段和mysql中的字段不匹配

例如:
这里就查询不到 name了

除了把名字改过来, 还可以使用 resultMap

<resultMap id="baseMap" type="com.example.demo.model.User">
        <!-- 主键映射 -->
        <id column="userId" property="userId"></id>
        <!-- 普通映射 -->
        <result column="username" property="name"></result>
        <result column="password" property="password"></result>
    </resultMap>
    <select id="getAll" resultMap="baseMap">
        select * from user
    </select>

注意这里的resultMap的写法

5.5 想要在控制台查看 mybatis 的日志

在配置文件中添加代码

logging.level.com.example.demo=debug
mybaits.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

通过这样配置就能查看日志了

5.6 编写 MyBatis 更方便的插件

搜索 MyBatisX

下载之后 重启Idea
有这种鸟就是安装好了

6. 动态 SQL

6.1 if 标签

在填写表单的时候 经常会有一些字段必须要填写, 一些字段不必要填写, 那么这种情况就需要用的动态SQL的if标签

xml的演示

<insert id="insert4" useGeneratedKeys="true" keyColumn="blogId" keyProperty="blogId">
        insert into blog(
        title,
        <if test="content != null">
        content,
        </if>
        postTime,userId) values (#{title},
        <if test="content != null">
        #{content},
        </if>
        #{postTime},#{userId})
    </insert>

注意这里的 if标签后面的test中的content是传入的属性,不是数据库中的字段.

6.2 trim 标签

当所有字段都是非必填项, 此时使用 if 标签就满足不了了

如 title是必填项, 后面都是非必填项, 此时sql拼装出来 就会变成
insert into blog(title,) values (title,) 这里的逗号就会导致sql报错.
<trim> 标签中有如下属性:

  • prefix: 表示整个语句块, 以prefix的值作为前缀
  • suffix: 表示整个语句块, 以suffix的值作为后缀
  • prefixOverrides: prefixOverrides的值表示整个语句块要去掉的前缀
  • suffixOverrides: suffixOverrides的值表示整个语句块要去掉的后缀
<insert id="insert5" useGeneratedKeys="true" keyProperty="userId" keyColumn="userId">
        insert into blog
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="title != null">
                title,
            </if>
            <if test="content != null">
                content,
            </if>
            <if test="postTime != null">
                postTime,
            </if>
            <if test="userId != null">
                userId,
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="title != null">
                #{title},
            </if>
            <if test="content != null">
                #{content},
            </if>
            <if test="postTime != null">
                #{postTime},
            </if>
            <if test="userId != null">
                #{userId},
            </if>
        </trim>
    </insert>

6.3 where 标签

如代码 select * from blog where userId=#{userId}
如果这里的 userId 是非必填项, 为空, 那么sql也会报错

下面的<where> 标签也可以使用<trim prefix="where" prefixOverrides="and">替换。

<select id="selectAll" resultType="com.example.demo.model.User">
        select * from blog
        <where>
            <if test="blogId != null">
                blogId = #{blogId}
            </if>
            <if test="userId != null">
                and userId = #{userId}
            </if>
        </where>
    </select>
  • <where>标签, 如果有查询条件就会生成where, 如果没有查询条件就不会生成where
  • where会判断第一个条件前面有没有and, 如果有就会去掉.

6.4 set 标签

更新的时候也会出现问题, 使用 <set> 标签来解决
set标签和where标签差不多

<update id="testUpdate">
        update user
        <set>
            <if test="username != null">
                username=#{username},
            </if>
            <if test="password != null">
                password=#{password},
            </if>
        </set>
        where userId=#{userId}
    </update>

6.5 foreach 标签

<foreach>标签有如下属性:

  • collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
  • item:遍历时的每⼀个对象
  • open:语句块开头的字符串
  • close:语句块结束的字符串
  • separator:每次遍历之间间隔的字符串
<delete id="testDe">
        delete from user where userId in
        <foreach collection="list" item="item" open="(" close=")" separator=",">
            #{item}
        </foreach>
    </delete>

相关文章