2.7 SpringBoot整合Mybatis



1.Mybatis 缓存机制

1.1 缓存概念

如果有大量相同的请求查询数据库,则数据库需要执行多次重复的sql,那么并发压力高,查询效率低. 如果引入缓存机制,则可以极大的提升用户的查询的效率。请添加图片描述

缓存介于服务器和数据库之间,其为了减轻数据库查询压力,提供服务器更高效的反馈速度出现。

1.2 Mybatis 提供缓存机制

  1. Mybatis中共俩级缓存
  2. 一级缓存 SqlSession 在同一个sqlSession内部 执行多次查询 缓存有效. 一级缓存默认开启状态.
  3. 二级缓存 SqlSessionFactory级别. 利用同一个工厂,创建的不同的SqlSession 可以实现数据的共享(缓存机制). 二级缓存
    默认也是开启的.
    请添加图片描述

1.3 一级缓存测试

    @Test
    public void testCache(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmpMapper userMapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> userList1 = userMapper.findAll();
        List<Emp> userList2 = userMapper.findAll();
        List<Emp> userList3 = userMapper.findAll();
        sqlSession.close();
    }

我们利用同一个SqlSession,执行多次数据库操作后,可以在控制台输出观察看,虽然执行了3次方法,但是sql只执行一次此时缓存就是生效的。要注意的时,使用缓存时,数据模型类要实现序列号接口。

1.4 二级缓存测试

1.4.1 指定使用二级缓存

语法: 在各自的xml 映射文件中 指定缓存标签.在这里插入图片描述

1.4.2 二级缓存测试

注意事项: sqlSession关闭之后,二级缓存才能生效

  //测试二级缓存
    @Test
    public void testCache2(){
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        EmpMapper empMapper = sqlSession1.getMapper(EmpMapper.class);
        List<Emp> list1 = empMapper.findAll();
        sqlSession1.close(); //sqlSession使用之后必须关闭.否则二级缓存不生效.
        //利用同一个SqlSessionFactory 创建不同的SqlSession
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        EmpMapper empMapper2 = sqlSession2.getMapper(EmpMapper.class);
        List<Emp> list2 = empMapper2.findAll();
        sqlSession2.close();
    }

1.4.3 注意事项

如果需要使用一级/二级缓存,则POJO对象必须实现序列化接口. 否则数据不可以被缓存.请添加图片描述
图解序列化规则:
请添加图片描述

在俩次查询中,相当于调用了俩次线程,线程A查询到的JAVA对象,线程B并不认识,这时就需要序列号排列字节信息,使线程B可以认识线程A查询到的JAVA对象,从而使线程B可以去使用。

2 SpringBoot整合Mybatis

2.1 创建项目

在这里插入图片描述

2.2 修改pom.xml文件

说明: 在新项目中添加依赖信息,可以直接赋值demo3中的pom内容

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--引入插件lombok 自动的set/get/构造方法插件  -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--mybatis依赖包-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <!--jdbc依赖包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

    </dependencies>

2.3 目录结构

在这里插入图片描述

这里要注意的是,mybatis.mappers是层级目录的结构,不是其名字中包含一个.,而是代表层级目录的意思。

2.4 SpringBoot整合Mybatis

2.4.1 编辑application.yml

SpringBoot整合Mybatis中,不再使用之前的mybatis-config.xml文件,而是使用springboot.yml配置文件。

#配置端口号
server:
  port: 8090

#管理数据源
spring:
  datasource:
    #高版本驱动使用
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    #设定用户名和密码
    username: root
    password: root

#SpringBoot整合Mybatis
mybatis:
  #指定别名包
  type-aliases-package: com.study.pojo
  #扫描指定路径下的映射文件
  mapper-locations: classpath:/mybatis/mappers/*.xml
  #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true

2.4.2 将Mapper接口交给容器管理

1. 通过@Mapper注解 管理对象

@Mapper //将Mapper接口交给Spring容器管理.
public interface UserMapper {

    List<User> findAll();
}

2. 通过包扫描的方式,管理mapper接口 编辑主启动类, 指定包扫描路径

@SpringBootApplication
//按照指定的包路径,扫描mapper的接口管理对象
@MapperScan("com.study.mapper")
public class SpringbootSsmApplication {

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

3. 编辑数据模型类

@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;

}

2.4.3 Mybatis 单元测试案例

1. 编辑测试类

@SpringBootTest
class SpringbootSsmApplicationTests {

    @Autowired  //注入指定的对象
    private UserMapper userMapper; //IDEA 编译提示 不影响执行

    /**
     * 测试SpringBoot整合Mybatis
     */
    @Test
    public void testFindAll(){
        List<User> userList = userMapper.findAll();
        System.out.println(userList);

    }
}

2. 编辑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">

<!--namespace是mybaits映射文件的唯一标识,与接口对应-->
<mapper namespace="com.study.mapper.UserMapper">

    <select id="findAll" resultType="User">
        select * from demo_user
    </select>
</mapper>

2.5 关于Mapper接口对象的说明

请添加图片描述
解释:

  1. 将接口交给Spring容器管理,spring会根据class类型,动态的选择创建代理对象. 最终将代理对象交给spring容器管理.

请添加图片描述

  1. 按照指定的包路径,扫描mapper的接口管理对象

2.5.1 代理方式介绍

2.5.1.1 JDK动态代理

特点:

  1. 要求被代理者,必须有接口.
  2. 默认条件下如果有接口,则使用JDK动态代理
2.5.1.2 CGLIB动态代理

特点:
1.不管被代理者是否有接口,都可以为其创建代理对象.
2. 代理对象是目标对象的子类. 继承关系.

结论:
1.Spring中如果有接口,默认使用JDK代理方式,如果没有接口,则默认使用CGLIB代理方式.
2.Spring5以后,自身接口对象创建代理对象时,使用cglib

2.5.2 IDEA 自动注入Mapper异常说明

我们在mapper类中添加的@Mapper注解,就可以很好的解决这个报错;

但是当项目并没有在mapper类中添加@Mapper注解,而是在主启动类上添加包扫描路径时,因为包扫描只有在主启动类启动时才会生效,所以会导致在项目启动前报此警告错误,这时只需要按照下图设置即可取消:
在这里插入图片描述

2.6 SSM框架案例

2.6.1 业务需求

用户访问URL: http://localhost:8090/findAll
返回值: List 的JSON串.

2.6.2 框架关系图

请添加图片描述

用户访问时,首先会调用SpringMVC控制的Controller层代码,Controller层注入被Spring框架管理的Service层代码,Service层需要注入Mybatis管理的Mapper层代码,其统一被SpringBoot管理,共同构成SpringBoot框架。

2.6.3 层级代码实现

在这里插入图片描述

2.6.4 编辑UserController

@RestController  //@ResponseBody 将list集合转化为json
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * URL: http://localhost:8090/findAll
     * 参数: 无
     * 返回值: List<User>
     */
    @RequestMapping("/findAll")
    public List<User> findAll(){

        return userService.findAll();
    }
}

2.6.5 编辑UserServicelmpl

@Service
public class UserServiceImpl implements UserService{

    @Autowired
    private UserMapper userMapper;


    @Override
    public List<User> findAll() {

        return userMapper.findAll();
    }
}

2.6.6 编辑UserMapper

  1. mapper接口
public interface UserMapper {

    List<User> findAll();
}

  1. mapper映射文件
<mapper namespace="com.study.mapper.UserMapper">

    <!--必须配置别名包-->
    <select id="findAll" resultType="User">
        select * from demo_user
    </select>
</mapper>

2.6.7 页面效果展现

打开浏览器搜索http://localhost:8090/findAll
在这里插入图片描述

3 框架代码案例练习

3.1 根据ID查询数据

3.1.1 需求说明

根据Id查询数据库
URL: http://localhost:8090/findUserById?id=1
返回值: User对象

3.1.2 编辑UserController

 /**
     * 需求: http://localhost:8090/findUserById?id=1
     * 参数接收: id=1
     * 返回值: User对象
     */
    @RequestMapping("/findUserById")
    public User findUserById(Integer id){

        return userService.findUserById(id);
    }

3.1.3 编辑UserService

 @Override
    public User findUserById(Integer id) {

        return userMapper.findUserById(id);
    }

3.1.4 编辑UserMapper

    User findUserById(Integer id);

编辑UserMapper.xml文件:

    <select id="findUserById" resultType="User">
        select * from demo_user where id = #{id}
    </select>

或者也可以使用注解的方式进行查询,但是要注意,注解和映射文件只能二选一,不能同时使用:

    @Select("select * from demo_user where id = #{id}")
    User findUserById(Integer id);

3.1.5 页面效果展现

在这里插入图片描述

3.2 根据age与sex查询数据

3.2.1 需求说明

根据age与sex查询数据库
URL: http://localhost:8090/findUserByAs?age=18&sex=%E5%A5%B3
返回值: List集合封装.

3.2.2 编辑UserController

    /*
     *URL:http://localhost:8090/findUserByAs?age=18&sex=%E5%A5%B3
     * 参数:age=18/sex=女
     * 返回值:List<集合>
     * 参数的接收:如果是多个参数,并且与属性名称一致,可以使用对象接收
     *
     */
    @RequestMapping("/findUserByAs")
    public List<User> findUserByAs(User user){
        return userService.findUserByAs(user);
    }

3.2.3 编辑UserService


    List<User> findUserByAs(User user);
    @Override
    public List<User> findUserByAs(User user){
        return userMapper.findUserByAs(user);
    }

3.2.4 编辑UserMapper

    @Select("select * from demo_user where age = #{age} and sex = #{sex}")
    List<User> findUserByAs(User user);

3.2.5 页面展示效果

在这里插入图片描述

3.3 Restful参数传递

3.3.1 业务需求

说明:要求修改id=1的数据,将name=“黑熊精” age=3000 sex=男,要求使用restFul的结构实现参数传递

常规get请求:http://localhost:8090/updateById?id=1&name=黑熊精&age=3000&sex=男

Restful请求路径:http://localhost:8090/updateById/1/黑熊精/3000/男

3.3.2 编辑UserController

    /*
     *URL:http://localhost:8090/updateById/1/黑熊精/3000/男
     * 参数:4个
     * 返回值:修改成功
     * restFul结构 参数分析 {属性名称}
     * 参数接收:
     *      1:单个参数使用@PathVariable Integer id接收
     *      2:多个参数接收 使用对象mvc自动提供的功能
     */
    @RequestMapping("/updateById/{id}/{name}/{age}/{sex}")
    public String updateById(User user){
        userService.updateById(user);
        return "用户修改成功";
    }

3.3.3 编辑UserService

 //spring整合mybatis之后,事务自动提交.
    @Override
    public void updateById(User user) {

        userMapper.updateById(user);
    }

3.3.4 编辑UserMapper

@Update("update demo_user set name=#{name},age=#{age},sex =#{sex} where id=#{id}")
    void updateById(User user);

4.练习

  1. 模糊查询 查询name中包含 "乔"的用户.
    http://localhost:8090/findUserByLike?name=乔 返回list集合
  2. 批量查询 查询id=1,3,5,7的数据
    http://localhost:8090/findUserByIds?ids=1,3,5,7 返回list集合
  3. 实现用户新增
    http://localhost:8090/saveUser/悟空/8000/男 返回成功的提示即可

4.1 模糊查询

编辑UserController

    /*
     *URL:http://localhost:8090/findUserByLike?name=乔
     * 参数:乔
     * 返回值: 返回list集合
     * restFul结构 参数分析 {属性名称}
     */
    @RequestMapping("/findUserByLike")
    public List<User> findUserByLike(String name){
        return userService.findUserByLike(name);
    }

编辑UserService

    List<User> findUserByLike(String name);
    @Override
    public List<User> findUserByLike(String name) {
        return userMapper.findUserByLile(name);
    }

编辑UserMapper

    @Select("select * from demo_user where name like \"%\"#{name}\"%\"")
    List<User> findUserByLile(String name);

4.2 批量查询

编辑UserController

    /*
    * 批量查询
    * http://localhost:8090/findUserByIds?ids=1,3,5,7
    * 返回list集合
    * 参数:ids=1,3,5,7
    * 返回值:List<User>
    * 知识点:MVC中参数,号分割的规则,应该使用数组接收mvc的规则
    * */
    @RequestMapping("/findUserByIds")
    public List<User> findUserByIds(Integer[] ids){
        return userService.findUserByIds(ids);
    }

编辑UserService

    List<User> findUserByIds(Integer[] ids);
    @Override
    public List<User> findUserByIds(Integer[] ids) {
        return userMapper.findUserByIds(ids);
    }

编辑UserMapper

    List<User> findUserByIds(Integer[] ids);

== 因为多个查询,所以查询语句需要写到UserMapper.xml中==

    <select id="findUserByIds" resultType="User">
        select * from demo_user where id in (
            <foreach collection="array" separator="," item="id">
                #{id}
            </foreach>
            )
    </select>

4.3 实现用户新增

编辑UserController

    /*
    *实现用户新增
    * http://localhost:8090/saveUser/悟空/8000/男
    * 返回成功的提示即可
    * 返回值:String
    * */
    @RequestMapping("/saveUser/{name}/{age}/{sex}")
    public String saveUser (User user){
        userService.saveUser(user);
        return "新增入库成功";
    }

编辑UserService

void saveUser(User user);
    @Override
    public void saveUser(User user) {
        userMapper.saveUser(user);
    }

编辑UserMapper

    @Insert("insert into demo_user (id,name,age,sex) values(null,#{name},#{age},#{sex} )")
    void saveUser(User user);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值