乐趣区

关于java:Spring-Boot初步学习03

基于前文 ”Spring Boot 初步学习 02″(点击返回查看), 曾经学习了 Spring 框架整合连接池的局部, 连接池就是用于与数据库连贯的工具, 那么本文就持续解说与数据库交互的局部 — 整合 Mybatis 框架.

Mybatis 框架

MyBatis 本是 apache 的一个开源我的项目 iBatis, 2010 年这个我的项目由 apache software foundation 迁徙到了 google code,并且改名为 MyBatis。2013 年 11 月迁徙到 Github。

iBATIS 一词来源于“internet”和“abatis”的组合,是一个基于 Java 的长久层框架。iBATIS 提供的长久层框架包含 SQL Maps 和 Data Access Objects(DAOs)

以上是百度中对于 Mybatis 框架的概述, 在我了解来说,Mybatis 框架是当初较为优良, 应用较为宽泛的一个长久层框架, 底层时基于 JDBC 去实现与数据库的交互, 并且在应用的过程中, 能够灵便去编写 SQL 语句, 并且对于 JDBC 做了优化与封装, 框架较小型, 但很实用.

现在我的项目中应用 Mybatis 框架时, 通常是由 Spring 框架进行整合, 去实现数据交互操作, 接下来就来说一下在 Spring Boot 中如何整合 Mybatis.

整合过程

应用过程

测试类 <–>mybatis<–>JDBC<–>Driver<–> 数据库

须要留神的是: 环节之间都是耦合于接口的, 这样的设计更加灵便, 更低耦合易保护批改.

创立我的项目

首先须要创立 Spring Boot 我的项目, 创立过程可见 Spring Boot 疾速入门案例.

当然如果曾经有创立好的我的项目间接应用即可.

增加 Mybatis 依赖

增加依赖时, 次要参考官网 mybatis.org/spring , 在 springboot 菜单中找到启动依赖, 复制粘贴至 pom.xml 中

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.1</version>
</dependency>

另一种形式: 右键我的项目中 pom.xml–>spring–>Edit Starters–> 搜寻 Mybatis, 增加依赖.
但要留神:springboot 并没有为 mybatis 指定版本, 以这种形式增加依赖, 须要本人指定版本.

简略配置

Spring Boot 特点就是零配置或简略配置, 在 mybatis 官网中, 尽管提供了一些配置, 然而也都是可选的, 不配置也能够失常运行, 这里倡议配置几点

#spring.mybatis
mybatis.configuration.default-statement-timeout=30
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.com.cy=DEBUG

前两个配置别离是: 设置 sql 超时工夫以及将数据库中的 user_name(这类下划线命名)主动转换为 userName(Java 中的驼峰命名)
第三个配置是 mybatis 中的 sql 日志的输入: 其中 com.cy 为我我的项目中的根包.

到这里对于 mybatis 与 Springboot 的整合就曾经实现了, 很不便简略, 前面是一些根底业务的实现.

业务实现

基于单个 ID 进行删除


创立数据层层接口

首先要创立数据层接口, 代码如下:

@Mapper
public interface GoodsDao {}

其中 @Mapper 注解是由 Mybatis 提供, 形容数据层接口的的注解, 用于通知 Spring 框架此接口的实现由 mybatis 创立,并将其实现类对象存储到 spring 容器, 交由 spring 治理.

创立数据层业务办法

须要在数据层接口中, 编写理论运行的业务办法, 代码如下:

@Mapper
public interface GoodsDao {
    /**
     * 基于商品 id 执行删除业务
     * @param id
     * @return 删除的行数
     */ 
     @Delete("delete from tb_goods where id=#{id}")
     public int deleteById(Integer id);
}

这种业务办法的编写模式, 是将简略的 sql 语句通过注解的模式进行定义, 写在办法上进行形容, 然而简单的 sql 语句还是要写在映射文件中(xml 文件中).

创立测试类

首先须要说的是, 在测试类中咱们申明属性时只通过 @Autowired 注解申明接口 (@Mapper 形容的接口) 不写实现类, 是因为基于咱们曾经将 springboot 和 mybatis 整合, 实现类会由 mybatis 创立再交由 spring 框架进行依赖注入(DI), 所以咱们只有 ” 面向接口 ” 即可, 理论创立由框架替咱们操心.

另外, 如果你想要去确定框架创立的实现类到底是什么呢?
能够通过打桩 (System.out.println(goodsDao.getClass().getName());) 或是加断点的形式失去答案.

测试类代码如下:

@SpringBootTest
public class GoodsDaoTests {
    @Autowired
    private GoodsDao goodsDao;
    @Test
    public void testDeleteById() {int rows = goodsDao.deleteById(10);
        System.out.println("rows="+rows);
    }
}

测试类是通过创立的实现类对象去调用 @Mapper 接口的业务办法, 实现对数据库的操作.

基于多个 ID 批量删除


上文中也有提到简单的 sql 语句还是要写在映射文件中 (xml 文件中) 利用动静 SQL 进行映射的, 这个案例就要实际操作一下.

创立 xml 映射文件

首先创立 xml 映射文件,springboot 我的项目中有严格的目录分类, 须要将 xml 文件放在 src/main/resource 目录下, 咱们能够再创立 mapper/goods 目录, 而后将咱们的 GoodsMapper.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> 标签并在其中增加 sql 标签及其语句, 此案例是依据 ID 批量删除, 代码如下:

<mapper namespace="com.cy.pj.goods.dao.GoodsDao">
      <delete id="deleteObjects">
          delete from tb_goods where id in 
        <foreach collection="ids" open="("
              item="id" separator="," close=")">
              #{id}        
        </foreach>
    </delete>
</mapper>

创立接口办法

在 @Mapper 接口中定义批量删除多个元素的办法, 代码如下:

@Mapper
public interface GoodsDao {
/**
     * 基于多个商品 id 删除
     * @param ids
     * @return 删除的行数
     */
    public int deleteObjects(@Param("ids")Integer... ids);
}

办法中传参为 ”(@Param(“ids”)Integer… ids)”, 这是可变参数, 能够了解为一类非凡的数组, 能够传入 0 /1/2…n 个数都可. 个别最新版本的 mybatis 能够不加 ”@Param(“ids”)” 这部分.

留神:xml 文件中的 namespace 与接口的全限定类名对应,SQL 标签的 ID 要与对应的接口办法名对应.

配置映射文件

当初咱们曾经写好了映射文件, 以及接口办法, 可如果有多个 xml 文件,spring 框架如何晓得那个是咱们要它进行治理的呢?

就须要在 application.properties 配置文件中增加配置如下:

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

“*” 为通配符, 象征所有的, 咱们的 xml 映射文件门路是在根目录下的 mapper/goods/GoodsMapper.xml, 就在配置的范畴内.

创立测试类

在 src/test/java 目录下编写测试类, 代码如下:

@SpringBootTest
public class GoodsDaoTests {
    @Autowired
    private GoodsDao goodsDao;
    @Test
    public void testDeleteObjects() {int rows = goodsDao.deleteObjects(6,7,8,9);
        System.out.println("rows="+rows);
    }
}

底层的执行程序是:
测试方法执行时, 咱们调用接口实现类的办法, 实现类外部会检测接口办法上是否有定义 sql 映射; 如果没有会基于接口类全名找到对应的配置的映射文件, 而后再基于办法名找到对应映射文件中的标签, 进而获取 sql 映射.

加强 SQL 语句可靠性

以上曾经实现了咱们的要求, 然而在 xml 映射文件中写简单 SQL 语句时, 咱们须要增强 SQL 语句的可靠性, 尤其是删除语句, 在对数据库进行操作时, 删除语句永远是咱们最须要小心的!

咱们须要思考到传入各种数据的状况, 如上文所写的:

<mapper namespace="com.cy.pj.goods.dao.GoodsDao">
      <delete id="deleteObjects">
          delete from tb_goods where id in 
          <foreach collection="ids" open="("
              item="id" separator="," close=")">
              #{id}        
          </foreach>
    </delete>
</mapper>

当咱们如果什么都不传时,SQL 语句就变为:delete from tb_goods where id in ;这样就会报错, 所以咱们能够增加动静 SQL 欠缺! 如下:

<mapper namespace="com.cy.pj.goods.dao.GoodsDao">
      <delete id="deleteObjects">
          delete from tb_goods
            <if test="ids!=null and ids.length>0">
                where id in
                <foreach collection="ids" open="("
                        item="id" separator="," close=")">
                    #{id}        
                </foreach>
            </if>
    </delete>
</mapper>

退出 <if> 标签进行判断, 排除了传入 null 的状况, 然而又发现 ids 不为 null 时能够失常执行, 但如果 ids 为 null, 没进入判断,SQL 语句是没有语法问题, 然而执行就变为:delete from tb_goods, 删除整个表, 在工作中这就是铸成大错了! 所以还须要进一步改良, 如下再退出 <where> 标签:

<mapper namespace="com.cy.pj.goods.dao.GoodsDao">
    <delete id="deleteObjects">
        delete from tb_goods
        <where>
            <if test="ids!=null and ids.length>0">
                id in <!-- (1,2,3,4) -->
                <foreach collection="ids" open="("
                        item="id" separator="," close=")">
                    #{id}        
                </foreach>
            </if>
            or 1=2
        </where>
    </delete>
  </mapper>

这样就解决了所有状况能够平安应用了.

退出移动版