零基礎(chǔ)學(xué)習(xí)SpringBoot(二)--集成MyBatis以及開啟事務(wù)

1. SpringBoot集成MyBatis

1.1 準(zhǔn)備數(shù)據(jù)庫

  • 啟動(dòng)數(shù)據(jù)庫,并通過Navicat連接


    image
  • 創(chuàng)建新的數(shù)據(jù)庫springboot,指定數(shù)據(jù)庫字符編碼為utf-8, 并創(chuàng)建表t_person

image
  • 向表中插入幾條數(shù)據(jù)
image

1.2 創(chuàng)建新項(xiàng)目

image

1.3 在pom.xml中添加相關(guān)jar依賴

<!--MyBatis 整合SpringBoot的起步依賴-->
 <dependency>
     <groupId>org.mybatis.spring.boot</groupId>
     <artifactId>mybatis-spring-boot-starter</artifactId>
     <version>2.1.3</version>
 </dependency>

 <!--MySql 的驅(qū)動(dòng)依賴-->
 <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
 </dependency>

1.4 在SpringBoot的核心配置文件application.properties中配置數(shù)據(jù)源

根據(jù)自己數(shù)據(jù)庫的信息修改以下內(nèi)容

server:
   # 配置內(nèi)嵌Tomcat端口號(hào)
   port: 8888
   servlet:
   # 配置項(xiàng)目上下文根
     context-path: /springboot-web

# 配置數(shù)據(jù)源
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8
    username: root
    password: 12345678

1.5 代碼實(shí)現(xiàn)

1.5.1 使用Mybatis反向工程生成接口、映射文件以及實(shí)體Bean
  • 創(chuàng)建Mybatis反向工程配置文件 GeneratorMapper.xml

  • 在pom.xml文件中添加反向工程依賴

<!--Mybatis 代碼動(dòng)生成插件-->
 <plugin>
   <groupId>org.mybatis.generator</groupId>
   <artifactId>mybatis-generator-maven-plugin</artifactId>
   <version>1.3.6</version>
   <configuration>
     <!--配置文件的位置-->
     <configurationFile>GeneratorMapper.xml</configurationFile>
     <verbose>true</verbose>
     <overwrite>true</overwrite>
   </configuration>
 </plugin>
  • 修改GeneratorMapper.xml配置
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE generatorConfiguration
 PUBLIC  "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
 "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>

   <!--指定連接數(shù)據(jù)庫的JDBC驅(qū)動(dòng)包所在位置, 指定到你本地的完整路徑-->
   <classPathEntry location="/Volumes/developer/workspace/java-workspace/springboot/springboot-web/mysql-connector-java-8.0.25.jar"/>
   <!-- 配置 table 表信息內(nèi)容體,targetRuntime 指定采用 MyBatis3 的版本 -->
   <context id="tables" targetRuntime="MyBatis3">
   <!-- 抑制生成注釋,由于生成的注釋都是英文的,可以不讓它生成 -->
   <commentGenerator>
     <property name="suppressAllComments" value="true" />
   </commentGenerator>

   <!-- 配置數(shù)據(jù)庫連接信息 -->
   <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
     connectionURL="jdbc:mysql://localhost:3306/springboot?useUnicode=true&amp;characterEncoding=UTF-8&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=GMT%2B8&amp;nullCatalogMeansCurrent=true"
     userId="root"
     password="12345678">
   </jdbcConnection>
   <!-- 生成 model 類,targetPackage 指定 model 類的包名, targetProject 指定生成的 model 放在 哪個(gè)工程下面-->
   <javaModelGenerator targetPackage="com.mufeng.springbootweb.model"
 targetProject="src/main/java">
     <property name="enableSubPackages" value="false" />
     <property name="trimStrings" value="false" />
   </javaModelGenerator>

   <!-- 生成 MyBatis 的 Mapper.xml 文件,targetPackage 指定 mapper.xml 文件的包名, targetProject 指定生成的 mapper.xml 放在哪個(gè)工程下面 -->
   <sqlMapGenerator targetPackage="com.mufeng.springbootweb.mapper"
     targetProject="src/main/java">
     <property name="enableSubPackages" value="false" />
   </sqlMapGenerator>

   <!-- 生成 MyBatis 的 Mapper 接口類文件,targetPackage 指定 Mapper 接口類的包名, targetProject 指定生成的 Mapper 接口放在哪個(gè)工程下面 -->
   <javaClientGenerator type="XMLMAPPER"
     targetPackage="com.mufeng.springbootweb.mapper" targetProject="src/main/java">
     <property name="enableSubPackages" value="false" />
   </javaClientGenerator>

   <!-- 數(shù)據(jù)庫表名及對(duì)應(yīng)的 Java 模型類名 -->
   <table tableName="t_person" domainObjectName="Person"
     enableCountByExample="false"
     enableUpdateByExample="false"
     enableDeleteByExample="false"
     enableSelectByExample="false"
     selectByExampleQueryId="false"/>
   </context>

</generatorConfiguration>
  • 運(yùn)行插件,生成相關(guān)文件
image
image
1.5.2 在controller包下創(chuàng)建PersonController并編寫代碼
package com.mufeng.springbootweb.controller;

import com.mufeng.springbootweb.model.Person;
import com.mufeng.springbootweb.services.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class PersonController {

   @Autowired
   private PersonService personService;

   @RequestMapping(value = "/springboot/getPersonDetails")
   @ResponseBody
   public Object getPersonDetails(){
     Person person = personService.findPersonById(1);
     return person;
   }

}
1.5.3 在Service包下創(chuàng)建service接口并編寫代碼
package com.mufeng.springbootweb.services;

import com.mufeng.springbootweb.model.Person;

public interface PersonService {

   /**
   * 根據(jù)用戶標(biāo)識(shí)獲取用戶詳情
   * @param id
   * @return
   */
   Person findPersonById(Integer id);

}
1.5.4 在 service.impl 包下創(chuàng)建 service 接口并編寫代碼
package com.mufeng.springbootweb.services.impl;

import com.mufeng.springbootweb.mapper.PersonMapper;
import com.mufeng.springbootweb.model.Person;
import com.mufeng.springbootweb.services.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PersonServiceImpl implements PersonService {

   @Autowired
   private PersonMapper personMapper;

   @Override
   public Person findPersonById(Integer id) {
     return personMapper.selectByPrimaryKey(id);
   }
}
1.5.5 在 Mybatis 反向工程生成的 StudentMapper 接口上加一個(gè) Mapper 注解

@Mapper 作用:mybatis 自動(dòng)掃描數(shù)據(jù)持久層的映射文件及 DAO 接口的關(guān)系

package com.mufeng.springbootweb.mapper;

import com.mufeng.springbootweb.model.Person;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface PersonMapper {
   int deleteByPrimaryKey(Integer id);

   int insert(Person record);

   int insertSelective(Person record);

   Person selectByPrimaryKey(Integer id);

   int updateByPrimaryKeySelective(Person record);

   int updateByPrimaryKey(Person record);
}

注意:默認(rèn)情況下,MyBatis的xml映射文件不會(huì)編譯到target的class目錄下,所以我們需要在pom.xml中配置resource

    <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>
                        **/*.xml
                    </include>
                </includes>
            </resource>
        </resources>

1.6 啟動(dòng)Application應(yīng)用,訪問測試

image

1.7 在運(yùn)行的主類上添加mapper掃描注解

注釋掉PersonMapper接口上的@Mapper注解

package com.mufeng.springbootweb.mapper;

import com.mufeng.springbootweb.model.Person;
import org.apache.ibatis.annotations.Mapper;

//@Mapper
public interface PersonMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Person record);

    int insertSelective(Person record);

    Person selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Person record);

    int updateByPrimaryKey(Person record);
}

在運(yùn)行主類Application上加@MapperScan("com.mufeng.springbootweb.mapper")

package com.mufeng.springbootweb;

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

@SpringBootApplication
@MapperScan("com.mufeng.springbootweb.mapper")
public class SpringbootWebApplication {

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

}

運(yùn)行測試結(jié)果

image

1.8 接口和映射文件分開

  • 修改GeneratorMapper.xml 文件中Mapper映射文件生成目標(biāo)位置, 目標(biāo)指向resources下的mapper文件夾下
        <!-- 生成 MyBatis 的 Mapper.xml 文件,targetPackage 指定 mapper.xml 文件的包名, targetProject 指定生成的 mapper.xml 放在哪個(gè)工程下面 -->
        <sqlMapGenerator targetPackage="mapper"
                         targetProject="src/main/resources">
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
  • 重新運(yùn)行代碼生成插件
image

把之前生成的映射文件刪除掉

  • 在application.yml配置文件中需要指定映射文件的位置,這個(gè)配置只有接口和映射文件不再同一個(gè)包的情況下,才需要指定
mybatis:
  mapper-locations: classpath:mapper/*.xml

2. SpringBoot的事務(wù)支持

SpringBoot 使用事務(wù)非常簡單,底層依然采用的是Spring本身提供的事務(wù)管理

  • 在入口類中使用注解@EnableTransactionManagement 開啟事務(wù)支持

  • 在訪問數(shù)據(jù)庫的Service方法上添加注解@Transactional即可

在PersonController中添加更新用戶的方法
    @RequestMapping(value = "/springboot/updatePersonById")
    @ResponseBody
    public Object updatePersonById(){
        int count = 0;
        try{
            Person person = new Person();
            person.setId(1);
            person.setName("MuFeng_update");
            person.setAge(20);
            count = personService.updatePersonById(person);
        }catch (Exception e){
            e.printStackTrace();
            return "fail";
        }
        return count;
    }
在PersonService接口中添加更新用戶的方法
    /**
     * 根據(jù)用戶id更新用戶信息
     * @param person
     * @return
     */
    int updatePersonById(Person person);
在PersonServiceImpl接口實(shí)現(xiàn)類中更新用戶信息方法進(jìn)行實(shí)現(xiàn),并主動(dòng)制造一個(gè)異常拋出
    @Override
    public int updatePersonById(Person person) {
        int updateCount = personMapper.updateByPrimaryKeySelective(person);
        System.out.println("更新結(jié)果:" + updateCount);
        //在此構(gòu)造一個(gè)除數(shù)為 0 的異常,測試事務(wù)是否起作用
        int a = 10/0;
        return updateCount;
    }
運(yùn)行并測試未開啟事務(wù)的情況
image
image

拋出了異常但是數(shù)據(jù)修改成功了,我們需要做的是在動(dòng)作出現(xiàn)異常時(shí),所有的增刪改的操作都要回滾

在PersonServiceImpl更新的實(shí)現(xiàn)方法上添加@Transactional注解
    @Override
    @Transactional
    public int updatePersonById(Person person) {
        int updateCount = personMapper.updateByPrimaryKeySelective(person);
        System.out.println("更新結(jié)果:" + updateCount);
        //在此構(gòu)造一個(gè)除數(shù)為 0 的異常,測試事務(wù)是否起作用
        int a = 10/0;
        return updateCount;
    }
在Application類上加@EnableTransactionManagement注解開始事務(wù)支持
@SpringBootApplication
@MapperScan("com.mufeng.springbootweb.mapper")
@EnableTransactionManagement
public class SpringbootWebApplication {

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

}

@EnableTransactionManagement是可選的,但是業(yè)務(wù)方法上必須添加@Transactional事務(wù)才生效

修改Controller的修改用戶信息的代碼
@RequestMapping(value = "/springboot/updatePersonById")
    @ResponseBody
    public Object updatePersonById(){
        int count = 0;
        try{
            Person person = new Person();
            person.setId(1);
            person.setName("MuFeng_update");
            person.setAge(25);
            count = personService.updatePersonById(person);
        }catch (Exception e){
            e.printStackTrace();
            return "fail";
        }
        return count;
    }
運(yùn)行測試
image
image

同樣拋出了異常,但是數(shù)據(jù)庫的年齡信息還是之前的20,并沒有被修改,說明我們的事務(wù)開啟成功了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容