SpringBoot-26-整合持久层-整合Mybatis框架

8.3 整合Mybatis框架
  • MyBatis 是一个半自动化的 ORM 框架,所谓半自动化是指 MyBatis 只支持将数据库查出的数据映射到 POJO 实体类上,而实体到数据库的映射则需要我们自己编写 SQL 语句实现,相较于Hibernate 这种完全自动化的框架,Mybatis 更加灵活,我们可以根据自身的需求编写 sql 语句来实现复杂的数据库操作。
  • 为整合Mybatis框架,MyBatis 也开发了一套基于 Spring Boot 模式的 starter:mybatis-spring-boot-starter。
  • 导入依赖
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <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>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.11</version>
        </dependency>
        <!--springboot中自带了log4j-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <!--非spring-boot官方-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
  • 在application.yml配置文件中配置整合mybatis配置,配置数据源并整合mybatis,配置别名和mapper/*.xml映射文件
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/jdbcstudy?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimeZone=UTC
    type: com.alibaba.druid.pool.DruidDataSource

    #SpringBoot默认是不注入这些的,需要自己绑定
    #druid数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许报错,java.lang.ClassNotFoundException: org.apache.Log4j.Priority

    #则导入log4j 依赖就行
    filters: stat,wall,log4j2
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
    
    #整合mybatis
mybatis:
  #扫描实体类的位置,在此处指明扫描实体类的包,在 mapper.xml 中就可以不写实体类的全路径名
  type-aliases-package: com.zk.pojo
  # 指定 mapper.xml 的位置
  mapper-locations: classpath:mybatis/mapper/*.xml
  configuration:
  	#默认开启驼峰命名法,可以不用设置该属性
  	map-underscore-to-camel-case: true

注意:使用 MyBatis 时,必须配置数据源信息,例如数据库 URL、数据库用户型、数据库密码和数据库驱动等。

  • 创建实体类pojo/User
package com.zk.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

/**
 * @author CNCLUKZK
 * @create 2022/8/3-19:20
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private String password;
    private String email;
    private Date birthday;

    public User(String name, String password, String email, Date birthday) {
        this.name = name;
        this.password = password;
        this.email = email;
        this.birthday = birthday;
    }
}
  • 创建com.zk.mapper.UserMapper接口,注意@Mapper标识是mybatis的mapper类
package com.zk.mapper;

import com.zk.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

/**
 * @author CNCLUKZK
 * @create 2022/8/3-19:22
 */
//此注解标识是mybatis的mapper类
@Mapper
@Repository
public interface UserMapper {
    //接口里面可以放静态常量和抽象方法


    int addUser(User user);

    int deleteUser(Map map);

    int updateUser(User user);

    User getUser(Map map);

    List<User> getUsers(Map map);

}
  • 方式2:可以在启动类配置mapper扫描包,如果没有在Mapper接口上配置@Mapper注解

当 mapper 接口较多时,我们可以在 Spring Boot 主启动类上使用 @MapperScan 注解扫描指定包下的 mapper 接口,而不再需要在每个 mapper 接口上都标注 @Mapper 注解。

@SpringBootApplication
//@MapperScan("com.zk.mapper")  扫描包
public class SpringbootData03Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootData03Application.class, args);
    }

}
  • 在resources/mybatis/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.zk.mapper.UserMapper">
    <sql id="sql1">
        <where>
            <if test="id != null">
                and id = #{id}
            </if>
            <if  test="name != null and name != ''">
                and NAME like concat ( '%',#{name},'%')
            </if>
            <if test="password != null and password != ''">
                and PASSWORD = #{password}
            </if>
        </where>
    </sql>
    <!--application.yml 中通过 type-aliases-package 指定了实体类别名-->
    <insert id="addUser" parameterType="user">
        INSERT INTO jdbcstudy.users(NAME,PASSWORD,email,birthday)
            VALUES(#{name},#{password},#{email},#{birthday})
    </insert>

    <delete id="deleteUser" parameterType="map">
        delete from jdbcstudy.users
        <include refid="sql1"></include>
    </delete>

    <update id="updateUser" parameterType="user">
        update jdbcstudy.users
        <set>
            <if test="name != null">
                NAME = #{name},
            </if>
            <if test="password != null">
                PASSWORD = #{password},
            </if>
            <if test="email != null">
                email = #{email},
            </if>
            <if test="birthday != null">
                birthday = #{birthday},
            </if>
        </set>
        <where>
            <if test="id != null">
                and id = #{id}
            </if>
        </where>
    </update>

    <select id="getUser" parameterType="map" resultType="user">
        select * from jdbcstudy.users
        <include refid="sql1"></include>
    </select>

    <select id="getUsers" parameterType="map" resultType="user">
        select * from jdbcstudy.users
        <include refid="sql1"></include>
    </select>


</mapper>

使用 Mapper 进行开发时,需要遵循以下规则:

  • mapper 映射文件中 namespace 必须与对应的 mapper 接口的完全限定名一致。
  • mapper 映射文件中 statement 的 id 必须与 mapper 接口中的方法的方法名一致
  • mapper 映射文件中 statement 的 parameterType 指定的类型必须与 mapper 接口中方法的参数类型一致。
  • mapper 映射文件中 statement 的 resultType 指定的类型必须与 mapper 接口中方法的返回值类型一致。
  • 在com.zk.controller包下创建UserController
package com.zk.controller;

import com.zk.mapper.UserMapper;
import com.zk.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author CNCLUKZK
 * @create 2022/8/3-19:57
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserMapper userMapper;

    @GetMapping("/addUser")
    public String addUser(){
        userMapper.addUser(new User("hany","123456","123456@163.com",new Date()));
        //重定向到列表页请求
        return "addBook-ok";
    }

    @GetMapping("/deleteUser/{id}")
    public String deleteUser(@PathVariable("id") String id){
        Map<String,String> map = new HashMap();
        map.put("id", id);
        int result = userMapper.deleteUser(map);
        return "deleteUser-ok";
    }

    @GetMapping("/updateUser")
    public String updateUser(){
        userMapper.updateUser(new User(4,"hany","123456","123456@163.com",new Date()));
        return "updateBook-ok";
    }

    @GetMapping("/getUsers")
    public List<User> getUsers(){
        Map<String,String> map = new HashMap(15);
        List<User> users =  userMapper.getUsers(map);
        for (User user:users) {
            System.out.println(user.toString());
        }
        return users;
    }
}
  • 然后访问http://127.0.0.1:8080/user/addUser(增加用户)、http://127.0.0.1:8080/user/deleteUser/4(删除用户)、http://127.0.0.1:8080/user/getUsers(查看)、http://127.0.0.1:8080/user/updateUser(修改)进行测试
  • springboot直接内置事务
  • 补充:注解方式实现dao接口

mapper 映射文件其实就是一个 XML 配置文件,它存在 XML 配置文件的通病,即编写繁琐,容易出错。即使是一个十分简单项目,涉及的 SQL 语句也都十分简单,我们仍然需要花费一定的时间在mapper 映射文件的配置上。

为了解决这个问题,MyBatis 针对实际实际业务中使用最多的“增伤改查”操作,分别提供了以下注解来替换 mapper 映射文件,简化配置:

  • @Select
  • @Insert
  • @Update
  • @Delete
  • 可以通过注解,基本可以满足我们对数据库的增删改查操作,例如
@Mapper
public interface UserMapper {
    @Select("select * from user where user_name = #{userName,jdbcType=VARCHAR} and password = #{password,jdbcType=VARCHAR}")
    List<User> getByUserNameAndPassword(User user);
    @Delete("delete from user where id = #{id,jdbcType=INTEGER}")
    int deleteByPrimaryKey(Integer id);
    @Insert("insert into user ( user_id, user_name, password, email)" +
            "values ( #{userId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR})")
    int insert(User record);
    @Update(" update user" +
            "    set user_id = #{userId,jdbcType=VARCHAR},\n" +
            "      user_name = #{userName,jdbcType=VARCHAR},\n" +
            "      password = #{password,jdbcType=VARCHAR},\n" +
            "      email = #{email,jdbcType=VARCHAR}\n" +
            "    where id = #{id,jdbcType=INTEGER}")
    int updateByPrimaryKey(User record);
}

注意事项:

mapper 接口中的任何一个方法,都只能使用一种配置方式,即注解和 mapper 映射文件二选一,但不同方法之间,这两种方式则可以混合使用,例如方法 1 使用注解方式,方法 2 使用 mapper 映射文件方式。

我们可以根据 SQL 的复杂程度,选择不同的方式来提高开发效率。

  • 如果没有复杂的连接查询,我们可以使用注解的方式来简化配置;
  • 如果涉及的 sql 较为复杂时,则使用 XML (mapper 映射文件)的方式更好一些。
下一篇:SpringBoot-27-springSecurity(安全:认证授权)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值