溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring boot整合Mybatis實(shí)現(xiàn)級(jí)聯(lián)一對(duì)多CRUD操作的完整步驟

發(fā)布時(shí)間:2020-09-01 12:05:05 來源:腳本之家 閱讀:265 作者:wx5c7f616d835a9 欄目:編程語言

前言

關(guān)系型數(shù)據(jù)庫(kù)中,隨處可見表之間的連接,對(duì)級(jí)聯(lián)的表進(jìn)行增刪改查也是程序員必備的基礎(chǔ)技能。關(guān)于Spring Boot整合Mybatis在之前已經(jīng)詳細(xì)寫過,不熟悉的可以回顧Spring Boot整合Mybatis并完成CRUD操作,這是本文操作的基礎(chǔ)。本文先準(zhǔn)備一個(gè)測(cè)試的數(shù)據(jù)庫(kù),然后使用MyBatis Generator進(jìn)行部分代碼自動(dòng)生成,再以一個(gè)例子來展示稍微高級(jí)點(diǎn)的操作:使用Mybatis完成級(jí)聯(lián)一對(duì)多的CRUD操作。

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

數(shù)據(jù)庫(kù)用到三張表:user表,role表,user_role表。user表用來存儲(chǔ)用戶的信息;role表用來存儲(chǔ)角色信息;user_role表用來將user和role相關(guān)聯(lián),存儲(chǔ)user和role的映射關(guān)系,使得一個(gè)用戶可以有多個(gè)角色,每個(gè)角色對(duì)應(yīng)其中的一條記錄。

新建user表

CREATE TABLE user(
 id INT PRIMARY KEY AUTO_INCREMENT,
 username VARCHAR(20),
 password VARCHAR(20)
)

新建role表并插入數(shù)據(jù)

CREATE TABLE role(
 id INT PRIMARY KEY AUTO_INCREMENT,
 rolename VARCHAR(20)
)
INSERT INTO `role`(`rolename`) VALUES ('后臺(tái)');
INSERT INTO `role`(`rolename`) VALUES ('前端');
INSERT INTO `role`(`rolename`) VALUES ('客戶端');
INSERT INTO `role`(`rolename`) VALUES ('AI');
INSERT INTO `role`(`rolename`) VALUES ('大數(shù)據(jù)');

結(jié)果如圖:

Spring boot整合Mybatis實(shí)現(xiàn)級(jí)聯(lián)一對(duì)多CRUD操作的完整步驟

新建關(guān)聯(lián)表user_role

CREATE TABLE user_role(
 id INT PRIMARY KEY AUTO_INCREMENT,
 userid INT,
 roleid INT
)

自動(dòng)生成代碼

MyBatis Generator 是MyBatis 官方出品的一款代碼生成器,為所有版本的MyBatis以及版本2.2.0之后的iBATIS版本生成代碼。我們可以使用它自動(dòng)生成MyBatis的 mapper、dao、entity ,省去最簡(jiǎn)單的重復(fù)代碼編寫。更多詳細(xì)情況可以查看官網(wǎng)。

1、pom.xml添加依賴

   <!-- MyBatis Generator插件 -->
   <plugin>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-maven-plugin</artifactId>
    <version>1.3.7</version>
    <configuration>
     <verbose>true</verbose>
     <overwrite>true</overwrite>
    </configuration>
    <dependencies>
     <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.16</version>
     </dependency>
    </dependencies>
   </plugin>

2、在項(xiàng)目根目錄下面添加自動(dòng)生成代碼的配置文件generatorConfig.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>
 <!--配置文件信息-->
 <properties resource="application.properties"/>
 
 <!--defaultModelType="flat" 大數(shù)據(jù)字段,不分表 -->
 <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
  <property name="autoDelimitKeywords" value="true" />
  <property name="beginningDelimiter" value="`" />
  <property name="endingDelimiter" value="`" />
  <property name="javaFileEncoding" value="utf-8" />
  <plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
 
  <plugin type="org.mybatis.generator.plugins.ToStringPlugin" />
 
  <!-- 注釋 -->
  <commentGenerator >
   <property name="suppressAllComments" value="true"/><!-- 是否取消注釋 -->
   <property name="suppressDate" value="true" /> <!-- 是否生成注釋代時(shí)間戳-->
  </commentGenerator>
 
  <!--數(shù)據(jù)庫(kù)鏈接-->
  <jdbcConnection driverClass="${spring.datasource.driverClassName}"
      connectionURL="${spring.datasource.url}"
      userId="${spring.datasource.username}"
      password="${spring.datasource.password}">
  </jdbcConnection>
 
  <!-- 類型轉(zhuǎn)換 -->
  <javaTypeResolver>
   <!-- 是否使用bigDecimal, false可自動(dòng)轉(zhuǎn)化以下類型(Long, Integer, Short, etc.) -->
   <property name="forceBigDecimals" value="false"/>
  </javaTypeResolver>
 
  <!--生成Model類存放位置-->
  <javaModelGenerator targetPackage="com.shangguan.mybatis1.entity" targetProject="src/main/java">
   <property name="enableSubPackages" value="true"/>
   <property name="trimStrings" value="true"/>
  </javaModelGenerator>
 
  <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources" >
   <property name="enableSubPackages" value="false" />
  </sqlMapGenerator>
 
  <javaClientGenerator targetPackage="com.shangguan.mybatis1.dao" targetProject="src/main/java" type="XMLMAPPER" >
   <property name="enableSubPackages" value="false" />
  </javaClientGenerator>
 
  <!-- 數(shù)據(jù)庫(kù)表的信息 -->
  <table tableName="user" enableCountByExample="true" enableUpdateByExample="true" enableDeleteByExample="true" enableSelectByExample="true" selectByExampleQueryId="true">
   <generatedKey column="id" sqlStatement="Mysql" identity="true" />
  </table>
 
  <table tableName="role" enableCountByExample="true" enableUpdateByExample="true" enableDeleteByExample="true" enableSelectByExample="true" selectByExampleQueryId="true">
   <generatedKey column="id" sqlStatement="Mysql" identity="true" />
  </table>
 
  <table tableName="user_role" enableCountByExample="true" enableUpdateByExample="true" enableDeleteByExample="true" enableSelectByExample="true" selectByExampleQueryId="true">
   <generatedKey column="id" sqlStatement="Mysql" identity="true" />
  </table>
 
 </context>
</generatorConfiguration>

3、使用Maven生成代碼:

我使用的是Eclipse,工程目錄右鍵Run as --> Maven build,在Goals中輸入mybatis-generator:generate命令,點(diǎn)擊Run按鈕即可自動(dòng)生成代碼。

自動(dòng)生成代碼時(shí)遇到的一些坑

報(bào)錯(cuò)信息:

Establishing SSL connection without server's identity verification is not recommended.
According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL
connection must be established by default if explicit option isn't set.
For compliance with existing applications not using
SSL the verifyServerCertificate property is set to 'false'.
You need either to explicitly disable SSL by setting useSSL=false,
or set useSSL=true and provide truststore for server certificate verification.

意思是在說不建議在沒有服務(wù)器身份驗(yàn)證的情況下建立SSL連接。根據(jù)MySQL 5.5.45+、5.6.26+和5.7.6+的要求,如果沒有設(shè)置顯式選項(xiàng),則默認(rèn)情況下必須建立SSL連接。您需要通過設(shè)置useSSL=false顯式禁用SSL,或者設(shè)置useSSL=true并為服務(wù)器證書驗(yàn)證提供信任存儲(chǔ)。

解決方案:在配置文件application.properties中數(shù)據(jù)庫(kù)連接后面加上&useSSL=true。

雖然Maven提示“BUILD SUCCESS”,但是仔細(xì)看生成的代碼和數(shù)據(jù)庫(kù)是不匹配的,提示代碼被重寫,報(bào)錯(cuò)[WARNING] Table Configuration user matched more than one table (spring_boot..user,mysql..user,webshop..user,jeece-iyangcong..user)...具體信息如圖:

Spring boot整合Mybatis實(shí)現(xiàn)級(jí)聯(lián)一對(duì)多CRUD操作的完整步驟

這是因?yàn)镸ySQL 8.0版本驅(qū)動(dòng)將參數(shù)nullCatalogMeansCurrent的默認(rèn)值由true改為了false,在使用MyBatis Generator生成表對(duì)應(yīng)的xml等時(shí)會(huì)掃描整個(gè)服務(wù)器里面的全部數(shù)據(jù)庫(kù)中的表,而不是掃描對(duì)應(yīng)數(shù)據(jù)庫(kù)的表。

解決方案:在配置文件application.properties中數(shù)據(jù)庫(kù)連接后面加上&nullCatalogMeansCurrent=true。

如果不出意外的話,將會(huì)自動(dòng)生成3個(gè)實(shí)體類文件,3個(gè)dao層文件,3個(gè)mapper.xml。這些代碼很長(zhǎng)且沒有技術(shù)含量,在這里就不貼出來的,真有需要可以到文末的GitHub地址去查看。

開始CRUD

接下來需要在Service和ServiceImpl中對(duì)dao層進(jìn)行簡(jiǎn)單的封裝,估計(jì)大家都知道該怎么寫,在這里也先不貼代碼了,詳見文末的GitHub地址。

添加用戶

添加用戶的邏輯是這樣的:后臺(tái)需要分兩步處理前端傳過來的username,password和roleids。第一步把username和password存入user表;第二步把第一步生成的userid和前端傳過來的roleids存入user_role表。這兩個(gè)操作步驟顯然是滿足事務(wù)的ACID特性的。

Spring 支持編程式事務(wù)管理和聲明式事務(wù)管理兩種方式。編程式事務(wù)指的是通過編碼方式實(shí)現(xiàn)事務(wù);聲明式事務(wù)基于 AOP,將具體業(yè)務(wù)邏輯與事務(wù)處理解耦。聲明式事務(wù)管理使業(yè)務(wù)代碼邏輯不受污染, 因此在實(shí)際使用中聲明式事務(wù)用的比較多。聲明式事務(wù)有兩種方式,一種是在配置文件(xml)中做相關(guān)的事務(wù)規(guī)則聲明,另一種是基于 @Transactional 注解的方式。本文直接使用@Transactional注解實(shí)現(xiàn)事務(wù),因?yàn)檫@種方式操作簡(jiǎn)潔,代碼可讀性很高。

UserController中增加用戶的代碼如下:

 @RequestMapping("/addUser")
 @Transactional(rollbackFor={RuntimeException.class, Exception.class})
 public Result saveUser(@RequestParam(value = "username") String username, 
   @RequestParam(value = "password") String password, 
   @RequestParam(value = "roleids") List<Integer> roleids) {
  User user = new User();
  user.setUsername(username);
  user.setPassword(password);
  userService.addUser(user);
  for(int i=0;i<roleids.size();i++) {
   UserRole userRole = new UserRole();
   userRole.setUserid(user.getId());
   userRole.setRoleid(roleids.get(i));
   userRoleService.addUserRole(userRole);
  }
  return ResultUtils.result(States.errorCode.SUCCESS, "添加成功", null);
 }

使用PostMan測(cè)試添加用戶:

Spring boot整合Mybatis實(shí)現(xiàn)級(jí)聯(lián)一對(duì)多CRUD操作的完整步驟

Spring boot整合Mybatis實(shí)現(xiàn)級(jí)聯(lián)一對(duì)多CRUD操作的完整步驟

接口返回添加“添加成功”字樣,然后去數(shù)據(jù)庫(kù)中查看,user表中多了一條數(shù)據(jù),user_role表中也插入了三條數(shù)據(jù)。顯然,這正是需要的結(jié)果,這是一個(gè)正確的操作。

刪除用戶

刪除用戶的邏輯和添加用戶的邏輯很相似:第一步根據(jù)前端傳過來的id刪除user表中的記錄;第二步userid刪除user_role表中的記錄;這兩個(gè)步驟也是滿足事務(wù)特性,也是使用@Transactional注解來實(shí)現(xiàn)。

代碼如下:

  @RequestMapping("/deleteUserById")
  @Transactional(rollbackFor={RuntimeException.class, Exception.class})
  public Result deleteUserById(Integer id) {
    userService.deleteUserById(id);
    List<UserRole> list = userRoleService.selectByUserId(id);
    for(int i=0;i<list.size();i++) {
      userRoleService.deleteByPrimaryKey(list.get(i).getId());
    }
    return ResultUtils.result(States.errorCode.SUCCESS, "刪除成功", null);
  }

使用PostMan測(cè)試刪除用戶:

Spring boot整合Mybatis實(shí)現(xiàn)級(jí)聯(lián)一對(duì)多CRUD操作的完整步驟

接口返回添加“刪除成功”字樣,然后去數(shù)據(jù)庫(kù)中查看,user表中id為1的記錄被刪除了,user_role表中userid為1的三條記錄也都刪除了。顯然,這正是需要的結(jié)果。

修改用戶

修改用戶邏輯:在user表中修改username和password,同時(shí)在user_role表中修改用戶和角色的映射記錄。修改用戶和角色映射記錄也就是先按照userid進(jìn)行刪除記錄,然后再插入新的映射信息。在這里同樣使用@Transactional注解來實(shí)現(xiàn)事務(wù)。

代碼如下:

  @RequestMapping("/updateUser")
  @Transactional(rollbackFor={RuntimeException.class, Exception.class})
  public Result updateUser(@RequestParam(value = "id")Integer id, 
      @RequestParam(value = "username") String username, 
      @RequestParam(value = "password") String password, 
      @RequestParam(value = "roleids") List<Integer> roleids) {
    userService.updateUser(id, username, password);
    //查找user_role然后按照id進(jìn)行刪除
    List<UserRole> list = userRoleService.selectByUserId(id);
    for(int i=0;i<list.size();i++) {
      userRoleService.deleteByPrimaryKey(list.get(i).getId());
    }
    //插入新的roleids
    for(int i=0;i<roleids.size();i++) {
      UserRole record = new UserRole();
      record.setUserid(id);
      record.setRoleid(roleids.get(i));
      userRoleService.addUserRole(record);
    }
    return ResultUtils.result(States.errorCode.SUCCESS, "更新成功", null);
  }

注意:當(dāng)使用PostMan進(jìn)行測(cè)試的時(shí)候,發(fā)現(xiàn)報(bào)錯(cuò):org.apache.ibatis.binding.BindingException: Parameter 'username' not found.

Available parameters are [0, 1, 2, param3, param1, param2]。

解決辦法:在dao層的Mapper.java代碼的參數(shù)加上@param注解 。例如:

void updateByPrimaryKey(@Param("id")Integer id, 
@Param("username")String username, @Param("password")String 
password);

使用PostMan進(jìn)行測(cè)試修改用戶:

Spring boot整合Mybatis實(shí)現(xiàn)級(jí)聯(lián)一對(duì)多CRUD操作的完整步驟

返回結(jié)果沒有問題,再去數(shù)據(jù)庫(kù)查看,數(shù)據(jù)庫(kù)也沒有問題,更新操作完成。

查詢用戶信息

查詢用戶的信息不僅需要user表中的用戶信息,還需要user_role表中的用戶角色映射關(guān)系,還需要role表的角色信息。這也是需要表之間聯(lián)合的操作。

本文采用的方法是新建一個(gè)AccountDetail類來整合信息。

public class UserDetail {
  private Integer userid;
  private String username;
  private String password; 
  private List<Integer> roleids; 
  private List<String> rolenames;
  //省略getter和setter
}

這是整合信息的關(guān)鍵代碼:

public List<UserDetail> selectAll(){
  List<User> userList = new ArrayList<>();
  List<UserDetail> details = new ArrayList<>();
 
  try{
    userList = userMapper.selectAll();
    details = getUserDetails(userList);
  }catch(Exception e){
    e.printStackTrace();
    return details;
  }
  return details;
}
 
public List<UserDetail> getUserDetails(List<User> lists){
  List<UserDetail> details = new ArrayList<>();
  if(lists == null || lists.size() < 1){
    return details;
  }
  Map<Integer, String> nameMap = roleService.getNameMap();
  for(int i=0; i< lists.size();i++){
    User user = lists.get(i);
    UserDetail detail = new UserDetail();
 
    detail.setUserid(user.getId());
    detail.setUsername(user.getUsername());
    detail.setPassword(user.getPassword());
    List<Integer> roleids = new ArrayList<>();
    List<String> rolenames = new ArrayList<>();
    List<UserRole> userroles = userRoleMapper.selectByUserId(user.getId());
    for(int j=0;j<userroles.size();j++) {
      roleids.add(userroles.get(j).getRoleid());
      rolenames.add(nameMap.get(userroles.get(j).getRoleid()));
    }
    detail.setRoleids(roleids);
    detail.setRolenames(rolenames);
    details.add(detail);
  }
  return details;
}

這是封裝的接口:

@RequestMapping("/getAllUser")
public Result getAllUser() {
  List<UserDetail> list = userService.selectAll();
  return ResultUtils.result(States.errorCode.SUCCESS, "查詢成功", list);
}

使用PostMan進(jìn)行測(cè)試查詢用戶信息:

Spring boot整合Mybatis實(shí)現(xiàn)級(jí)聯(lián)一對(duì)多CRUD操作的完整步驟

可以看到這個(gè)接口返回了所有的用戶信息,包括用戶的基本信息和角色信息,準(zhǔn)確無誤。

總結(jié)

Spring和MyBatis實(shí)現(xiàn)一對(duì)多關(guān)聯(lián)的增刪改查也有多種方式:可以使用MyBatis來自定義SQL語句來實(shí)現(xiàn);也可以使用Spring的注解結(jié)合MyBatis自動(dòng)生成的代碼來實(shí)現(xiàn)。我更喜歡后者,因?yàn)橥ㄟ^Mybatis Generator自動(dòng)生成代碼以后,這些代碼就不需要再修改了,可以直接封裝service和controller。希望本文對(duì)大家有用。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI