框架技术SpringBoot ---SpringBoot集成Mybatis

SpringBoot框架


SpringBoot框架整合持久层框架,Mybatis


前面已经分享了SpringBoot的基本用法:建立SpringBoot项目,使用配置类的方式注册Servlet、Filter,使用application.yml注册相关配置项;接下来就是将Mybaits整合到SpringBoot中

最近有很多事情,CET-6刷分,软考,课程考试,准备八股…SpringBoot只能抱歉达到最简了

ORM操作MySQL

object relative mapping对象关系映射;Mybatis框架就是ORM的一种;这里主要分析通过Mybatis框架,读写MySQL数据

这里没有什么多difficult的地方,所以就直接上操纵,使用Windows+ R打开cmd窗口,打开mysql工具,在cfengbase数据库下面建立一张表student;表中3个字段name,id,class

mysql> DESC student;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| stuno    | int          | NO   | PRI | NULL    | auto_increment |
| stuname  | varchar(255) | YES  |     | NULL    |                |
| stuclass | varchar(255) | YES  |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

SpringBoot集成Mybaits步骤

  • 添加mybaits起步依赖:完成mybatis对象的自动配置、对象放在容器中【mybatis有自动配置的直接,会将mybatis的相关对象放到容器中】
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  <!-- mybaits起步依赖 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>

<!-- mysql驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

mybaits-starter默认使用的连接池是com.zaxxer的hikariCP; 这个连接池比其他的连接池速度更快; 起步依赖加入了mybatis和mybatis-spring、spring-jdbc等依赖;不需要再像SSM一样再加入

  • 在pom.xml指定资源插件,将src/main/java目录的xml文件读取移动到classPath中
  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
      <!-- 还要配置上原来编译资源的路径-->
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.*</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>
  • 创建实体类Student,这里easy
package cshen.model;

public class Student {
    private int stuno;
    private  String stuname;
    private String stuclass;

    public Student() {
    }

    public Student(int stuno, String stuname, String stuclass) {
        this.stuno = stuno;
        this.stuname = stuname;
        this.stuclass = stuclass;
    }

    public int getStuno() {
        return stuno;
    }

    public void setStuno(int stuno) {
        this.stuno = stuno;
    }

    public String getStuname() {
        return stuname;
    }

    public void setStuname(String stuname) {
        this.stuname = stuname;
    }

    public String getStuclass() {
        return stuclass;
    }

    public void setStuclass(String stuclass) {
        this.stuclass = stuclass;
    }

    @Override
    public String toString() {
        return getClass().getName().toString()  + "{" +   //this都可以省略不写
                "stuno=" + stuno +
                ", stuname='" + stuname + '\'' +
                ", stuclass='" + stuclass + '\'' +
                '}';
    }
}

这里重写toString方法的时候建议使用反射机制来获取类名,开闭原则

  • 创建Dao接口,创建方法,并在mapper文件中书写SQL语句
package cshen.dao;

import cshen.model.Student;
import org.apache.ibatis.annotations.Mapper;

/**
 * 告诉mybatis框架,为这个接口创建代理对象
 */
@Mapper
public interface StudentDao {
    public Student selectByName(String stuname);
}


<mapper namespace="cshen.dao.StudentDao">
    <select id="selectByName" resultType="cshen.model.Student">
        SELECT stuno,stuname,stuclass FROM student WHERE stuname = #{stuname}
    </select>
</mapper>
  • 创建Service和Controller层的对象
package cshen.service.impl;

import cshen.dao.StudentDao;
import cshen.model.Student;
import cshen.service.StudentService;

import javax.annotation.Resource;

@Service //生成单例对象放入容器
public class StudentServiceImpl implements StudentService {
    //动态代理生成了Dao对象放在容器中,直接取出注入
    @Resource
    private StudentDao studentDao;

    @Override
    public Student queryStudent(String stuName) {
        return studentDao.selectByName(stuName);
    }
}

这里只是为了演示SpringBoot整合Mybaits,业务逻辑是不可能如此简单的

package cshen.controller;

import cshen.model.Student;
import cshen.service.StudentService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

@Controller
public class StudentController {

    @Resource
    private StudentService studentService;

    @RequestMapping("/student/query")
    @ResponseBody
    public Student searchStudent(String stuName) {
        return studentService.queryStudent(stuName);
    }
}
  • 书写application.properties文件【数据库的连接信息】
###配置端口号
server:
  port: 8081
  servlet:
    context-path: /bootOrm
    encoding:  #全局过滤器
      charset: UTF-8
      force: true
###配置数据源
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cfengbase?serverTimezone=GMT%2B8
    username: cfeng
    password: a1234567890b

SpringBoot欢迎页面【默认首页】,如果不手动配置,那么系统默认static包下面的index.html为首页;如果想自定义可以 1. 通过controller中进行转发;Mapping为/; 2、编写webMVC的配置类,设置addViewController; 使用ViewControllerRegistory来进行注册

这样就成功完成了数据库的连接操作,与SSM相比简化了许多许多,最主要的就是再次封装,不用手动创建SqlSessionFactry等对象,还有就是mapper的扫描器就一个注解Mapper代替了😳

第一种方式: @Mapper注解

@Mapper: 放在dao接口的上面,每一个接口都需要使用这个注解 ----- 可以告诉mybaits这是dao接口,让其创建该接口的代理对象放入容器中供service使用

@Mapper
public interface StudentDao {
    public Student selectByName(String stuname);
}

但是这个注解的问题就是需要在每一个接口的上方都需要写,一旦操作的表的接口过多,就非常繁琐

第二种方式: @MapperScan

使用Mapper注解不方便,所以推荐使用@MapperScan;这个注解放在主类--- 也就是起始类【加SpringBootApplicaton注解】上方; 其参数就是Dao接口所在的包

package cshen;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("cshen.dao")  //这里是一个数组
public class BootApplication4 {

    public static void main(String[] args) {
        //执行操作返回的是容器对象;可以获取容器;并且使用ApplicationRunner接口操作
        SpringApplication.run(BootApplication4.class, args);
    }

}

查询之后正常使用

INFO 13468 --- [nio-8081-exec-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2022-03-30 20:19:36.443  INFO 13468 --- [nio-8081-exec-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.

可以看到hikari数据源成功进行了操作

这里的Mapper和MapperScan注解在之前的SSM中就是

就是这个MapperScannerConfiger扫描包,然后创建代理对象以供使用
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 相当于内部调用这个方法,所以需要factory对象,还需要接口的类型  看到是String类型的,使用value,不是ref-->
        <property name="sqlSessionFactoryBeanName" value="mySqlSession"/>
        <!-- 指定包名,包名是dao接口所在的包名,MapperScannerConfig会扫描这个包中所有的接口,
            都调用getMapper方法为每一个接口代理一个dao对象,创建好的所有的dao对象存放在容器中
         -->
        <property name="basePackage" value="cfeng.dao"/>
    </bean>

dao和xml文件分开 — yml中配置

之前的项目中,mapper文件和dao接口总是放在一起的,这不利于管理,因为java目录下应该都是java文件,xml文件应该放到Resource下面去

放到自定义的/resource/mapper文件夹下面,这时就出现了新的问题: 系统找不到mapper文件位置;所以需要在application中进行配置

##mapper文件分开管理--指定位置
mybatis:
  mapper-locations: classpath:mapper/*.xml   #mapper下面的所有的xml文件

需要注意像博主一样加入资源插件,不然又找不到Resource下面的静态资源了:happy:

这里之前没有配置日志,可以再进行配置【这里的mybatis下面的选项都是之前的Mybatis的主配置文件中的配置的选项】

mybatis:
  mapper-locations: classpath:mapper/*.xml   #mapper下面的所有的xml文件
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl    #输出到控制台

这样再执行一次

JDBC Connection [HikariProxyConnection@923951926 wrapping com.mysql.cj.jdbc.ConnectionImpl@45e81348] will not be managed by Spring
==>  Preparing: SELECT stuno,stuname,stuclass FROM student WHERE stuname = ?
==> Parameters: 王6(String)
<==    Columns: stuno, stuname, stuclass
<==        Row: 2, 王6, HC2004
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ec187c7]

可以看到就开启了日志,记录输出到控制台

现在就可以不需要上面插件中的java目录的编译了;因为java下面已经没有静态资源了;只用使用Resource即可【之前SSM中也可以进行指定,当时忘记说了,抱歉】

事务tx

Spring框架中使用事务: 使用aspectJ框架实现配置文件中实现事务;还有就是依赖@Transaction注解

当时需要再spring配置文件中指定一个事务管理其对象【事务管理器有很多种接口,不同的数据库有不同的类型,mybaits访问使用的就是DataSourceTransactionManager】

 <!-- 声明事务管理器对象 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 要说明连接的数据库的信息,知道为哪张表开启事务 -->
        <property name="dataSource" ref="myDataSource"/>
    </bean>
 <tx:annotation-driven transaction-manager="transactionManager"/>

加上注解驱动,就可以使用@Transactional方式实现事务,在参数中指定隔离级别和传播行为;AOP的实现也是动态代理,拿到原对象进行功能增强

在配置文件中说明声明式事务: 控制事务: 隔离级别,传播行为,超时时间

SpringBoot使用事务

SpringBoot只是对于Spring和SpringMVC进行简化,所以上面Spring的两种方式,都是可以使用的

业务方法加入@Transactional; 同时主启动类加上@TransactionManager

直接在业务方法上加上注解即可;如果不进行指定,那么就是数据库的默认隔离级别,传播行为是REQUIRED;在默认情况下,事务时默认自动提交的,

这里可以迅速新建一个插入学生的方法,在mapper文件中直接通过对象传参,这里就可以直接取得对象的同名参数【这和前面的Controller中自动取用返回的参数赋值给同名属性是相同的】

    <insert id="insertStudent">
        INSERT INTO student (stuno,stuname,stuclass) VALUES (#{stuno},#{stuname},#{stuclass})
    </insert>

这里的SQL语句后面加上括号,不然SQL语句就是错误的

 @Override
    public int addStudent(Student student) {
        int result = studentDao.insertStudent(student);
        System.out.println("执行了业务方法");
        //这里模拟抛出运行时异常
        int m = 10/0;  //算数异常; 如果是开发中按理就要回滚; 但是目前没有加事务,上面就会自动提交事务
        return result;
    }

那么接下来就使用注解来开启事务

@Override
    @Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED)
    public int addStudent(Student student) {
        int result = studentDao.insertStudent(student);
        System.out.println("执行了业务方法");
        //这里模拟抛出运行时异常
//        int m = 10/0;  //算数异常; 如果是开发中按理就要回滚; 但是目前没有加事务,上面就会自动提交事务
        return result;
    }

运行后,控制台抛出异常,java.lang.ArithmeticException: / by zero;查看数据库,数据没有添加成功

还有配置文件使用的方式都还是支持的,可以去看博主之前的Spring的事务的部分🌳

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值