springboot + mybatis入门整理

通常为了方便跳转到对应的xml文件,可安装 mybatisX插件

一、环境准备

pom.xml依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--属性校验-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
		<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pagehelper-spring-boot-starter.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis-spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.1-jre</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>${hutool-core.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>

        <!-- swagger -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>${swagger-knife4j.version}</version>
        </dependency>
        <!-- swagger -->

项目配置文件application.yml

server:
  port: 7071
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      one:
        max-active: 60 #最大连接数
        min-idle: 5 #最小连接数
        max-wait: 50000 #超时时间(ms)
mybatis:
  # 实体类起存放包名
  type-aliases-package: com.mybatis.demo
  # 接口的配置文件的位置
  mapper-locations: classpath:com/mybatis/demo/dao/../*.xml

二、项目结构

在这里插入图片描述

三、数据库建表初始化数据

drop table if exists t_user;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL COMMENT '姓名',
`age` int(3) DEFAULT NULL COMMENT '年龄',
`status` tinyint(1) DEFAULT 0 COMMENT '状态 0-启用 1-禁用',
`create_by` varchar(32) DEFAULT NULL,
`create_date` bigint(13) DEFAULT NULL,
`update_by` varchar (32) DEFAULT NULL,
`update_date` bigint(13) DEFAULT NULL,
`is_delete` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('wangwu', 25, 0, 1, 1, NULL1 1, 1);
INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('laoliu', 24, 0, 1, 1, 1, 1, 1);
INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('liudehua', 58, 0, 1, 1, 1, 1, 1);
INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('wuyifan', 39, 0, 1, 1, 1, 1, 1);
INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('wangyifei', 43, 0, 1, 1, 1, 1, 1);
INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('bagua', 36, 0, 1, 1, 1, 1, 1);
INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('luoyonghao', 56, 0, 1, 1, 1, 1, 1);
INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('qinwang', 63, 0, 1, 1, 1, 1, 1);
INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('liuao', 29, 0, 1, 1, 1, 1, 1);
INSERT INTO `mybatis`.`t_user` (`name`, `age`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES ('laowang', 36, 0, 1, 1, 1, 1, 1);

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@JsonInclude(JsonInclude.Include.NON_NULL)  # 字段值为null时不返回
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private  Boolean status;
    private String createBy;
    private Long createDate;
    private String updateBy;
    private Long updateDate;
    private Boolean isDelete;
}

四、业务逻辑CRUD

4.1、根据ID查询

UserController.java

@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @GetMapping("/getById")
    public JsonResult getById(@RequestParam("id") Integer id){
        return ResultEnum.SUCCESS.jsonResult(userService.getById(id));
    }
}

UserService.java

@Component
public interface  {
    User getById(Integer id);
}

UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao userDao;

    @Override
    public User getById(Integer id) {
        return userDao.getById(id);
    }

UseDao.java

@Mapper
public interface UserDao {
    User getById(@Param("id") Integer id);
}

UserDao.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.mybatis.demo.dao.user.UserDao">
    <select id="getById" resultType="user" parameterType="int">
        select * from t_user where id = #{id}
    </select>
</mapper>

启动项目,调用接口
在这里插入图片描述

注意:这里返回的数据都没有驼峰命名的字段,原因是数据库都是下划线分割的
想要解决驼峰命名无法封装数据的问题,有两种方案:

4.1.1、起别名方式解决

从结果日志可以看出, updateBy 等字段没有封装成功,时因为从数据哭中取到的字段为update_by,在实体类中不存在该字段,解决方案就是起别名让字段对应即可

    <select id="getById" resultType="user" parameterType="int">
        select id, name, age, status, create_by as createBy, create_date as createDate,
               update_by as updateBy, update_date as updateDate from t_user where id = #{id}
    </select>

以上代码写一次尚可,如果频繁读取该类表字段,重复代码较多,Mybatis提供了sql片段提高sql的复用
aql片段

<sql id="user_column">
        id, name, age, status, create_by as createBy, create_date as createDate,update_by as updateBy, update_date as updateDate
</sql>

修改sql语句

    <select id="getById" resultType="user" parameterType="int">
        select <include refid="user_column" /> from t_user where id = #{id}
    </select>

4.1.2、resultMap方式解决(推荐使用)

定义数据库字段与实体类属性名称的映射关系

<resultMap id="base_result_map" type="com.mybatis.demo.entity.user.User">
	<!--<result column="数据库字段名称" property="实体类属性"/>-->
    <result column="create_by" property="createBy"/>
    <result column="create_date" property="createDate"/>
    <result column="update_by" property="updateBy"/>
    <result column="update_date" property="updateDate"/>
    <result column="is_delete" property="isDelete"/>
</resultMap>

修改sql语句

<select id="getById" resultMap="base_result_map" parameterType="int">
    select * from t_user where id = #{id};
</select>

嵌套 sql 片段使用

<sql id="user_col_for_detail">
    id, name, age, status
</sql>
<select id="getById" resultMap="base_result_map" parameterType="int">
    select <include refid="user_col_for_detail" /> from t_user where id = #{id};
</select>

4.1.3、参数占位符

mybatis 提供了两种参数占位符

  • #{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值,底层使用的是 PreparedStatement,不存在SQL注入

  • ${} :拼接SQL,底层使用statement,会存在SQL注入问题

4.1.4、parameterType使用

4.1.5 SQL语句中特殊字段处理

4.2 多条件查询

Controller

@GetMapping("/getByManyCondition")
    public JsonResult getByManyCondition(@RequestParam("keyword") String keyword,
                                @RequestParam(value = "status", defaultValue = "0") Integer status){
        return ResultEnum.SUCCESS.jsonResult(userService.getByManyCondition(keyword, status));
    }

Service

List<User> getByManyCondition(String keyword, Integer status);

ServiceImpl

public List<User> getByManyCondition(String keyword, Integer status){
        return userDao.getByManyCondition(keyword, status);
    }

Dao

List<User> getByManyCondition(@Param("keyword") String keyword, @Param("status") Integer status);

Dao.xml(Mapper.xml文件)

<select id="getByManyCondition" resultMap="base_result_map">
    select * from `t_user`
    <where>
        <if test="keyword != null and keyword != ''">
            `name` like concat('%', #{keyword}, '%')
        </if>
        <if test="status != null">
            and `status` = #{status}
        </if>
    </where>
</select>

4.3 in

新增一个 t_user_detail 表,并创建对应的实体类 UserDetail

drop table if exists t_user_detail;
CREATE TABLE `t_user_detail` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(3) NOT NULL COMMENT '用户ID',
  `address` varchar(64) DEFAULT NULL COMMENT '地址',
  `mobile` varchar(16) DEFAULT NULL COMMENT '手机号',
  `create_by` varchar(32) DEFAULT NULL,
  `create_date` bigint(13) DEFAULT NULL,
  `update_by` varchar (32) DEFAULT NULL,
  `update_date` bigint(13) DEFAULT NULL,
  `is_delete` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `mybatis`.`t_user_detail` (`user_id`, `address`, `mobile`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES (1, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `mybatis`.`t_user_detail` (`user_id`, `address`, `mobile`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES (2, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `mybatis`.`t_user_detail` (`user_id`, `address`, `mobile`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES (3, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `mybatis`.`t_user_detail` (`user_id`, `address`, `mobile`, `create_by`, `create_date`, `update_by`, `update_date`, `is_delete`)
VALUES (4, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

Mybatis 实现 in 条件查询有三种实现方法($, List,[])

第一种方法:in 条件为拼接好的字符串

如果直接传入拼接好的where in 条件, 比如(‘111’,‘222’,‘333’),则需要使用${idList}传参,即绝对引用,而不能使用#, 如果使用#传参会被mybatis当成字符串再添加一层’'引号,导致错误.
优点:简单方便,高效,缺点:不能防止SQL注入

第二种方法:in 条件为List对象

in条件直接传入List对象,让mybatis再去拼接生成in条件,这个很麻烦,但是可以防止SQL注入

第三种方法:in 条件为String[] 数组

in条件直接传入[]数组对象,让mybatis再去拼接生成in条件,这个很麻烦,但是可以防止SQL注入
如果项目大,其实可以同时重载三种都实现,我一般都会这样,实现三种DAO接口,service层相同方法名,根据不同的模块不同的需求调用不同的实现层

Controller

    @GetMapping("/del1")
    public JsonResult delUser1(@RequestParam("idList") String idList){
        System.out.println(idList);
        return ResultEnum.SUCCESS.jsonResult(userService.deleteUserByIdList(idList, 0, 0));
    }

    @GetMapping("/del2")
    public JsonResult delUser2(@RequestParam List<String> idList){
        System.out.println(idList);
        return ResultEnum.SUCCESS.jsonResult(userService.deleteUserByIdList(idList, 0, 0));
    }

    @GetMapping("/del3")
    public JsonResult delUser3(@RequestParam String[] idList){
        System.out.println(idList);
        return ResultEnum.SUCCESS.jsonResult(userService.deleteUserByIdList(idList, 0, 0));
    }

Service:

int deleteUserByIdList(String idList,int delCount,int lastSort);

int deleteUserByIdList(List<String> idList, int delCount,int lastSort);

int deleteUserByIdList(String[] idList, int delCount,int lastSort);

Dao

//用这种写法方便,idList 直接拼接好,xml中用 in ${idList}接受参数
int deleteUserByIdList1(@Param("idList")String idList, @Param("delCount")int delCount, @Param("lastSort")int lastSort);

//用这种写法直接传List对象,xml中再写循环拼接,麻烦
int deleteUserByIdList2(@Param("idList")List<String> idList, @Param("delCount")int delCount, @Param("lastSort")int lastSort);

//用这种写法直接传String[]数组,xml中再写循环拼接,麻烦
int deleteUserByIdList3(@Param("idList")String[] idList, @Param("delCount")int delCount, @Param("lastSort")int lastSort);

Dao.xml(Mapper.xml文件)

    <delete id="deleteUserByIdList1" >
        update t_user set is_delete = 1 where id in ${idList};
    </delete>

    <delete id="deleteUserByIdList2" >
        update t_user set is_delete = 1 where id in
        <foreach collection="idList" item="id" separator="," open="(" close=")">
            ${id}
        </foreach>;
    </delete>

    <delete id="deleteUserByIdList3" >
        update t_user set is_delete = 1 where id in
        <foreach collection="idList" item="id" separator="," open="(" close=")">
            ${id}
        </foreach>;
    </delete>

4.4 mybatis插入后返回主键id的三种方式

mybatis 操作后默认返回受影响的条数,如插入数据后想返回插入数据的id,则需要自行配置,方法有下列三种

第一种:在xml文件,insert标签属性中,添加useGeneratedKeys = true和keyProperty=id
<insert id="addUser" parameterType="com.mybatis.demo.entity.user.User" useGeneratedKeys="true" keyProperty="id">
    insert into t_user (`name`, `age`, `status`)
    values (#{user.name}, #{user.age}, #{user.status});
</insert>
第二种:在xml文件,添加selectKey标签属性

各个属性值含义:

resultType:查询结果的类型;
keyProperty:把查询的值赋给谁;
order:在插入前还是后执行,id在insert语句插入之后才会生成id,所以要在插入之后执行,所以此处order=after;

<insert id="addUser" parameterType="com.mybatis.demo.entity.user.User">
    <selectKey keyProperty="id" resultType="integer" order="AFTER">
        select LAST_INSERT_ID()
    </selectKey>
    insert into t_user (`name`, `age`, `status`)
    values (#{user.name}, #{user.age}, #{user.status});
</insert>
第三种:在dao层用注解的方式,用@SelectKey注解

注解里面属性含义:
resultType:查询结果的类型,
keyProperty:把查询的值赋给谁;
statement:查找最后一个插入的id;
keyColumn:查询的是哪一列;
before:是否在插入之前执行, id在insert语句插入之后才会生成id,所以要在插入之后执行,所以此处before=false;

Dao

@SelectKey(statement = "select last_insert_id()", before = false, resultType = Integer.class, keyColumn = "id", keyProperty = "id")
@Insert("insert into t_user (`name`, `age`, `status`) values (#{user.name}, #{user.age}, #{user.status})")
int addUser(@Param("user") User user);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值