欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

mybatis水平分表實(shí)現(xiàn)動(dòng)態(tài)表名的項(xiàng)目實(shí)例

 更新時(shí)間:2022年07月29日 08:32:08   作者:先養(yǎng)只貓  
本文主要介紹了mybatis水平分表實(shí)現(xiàn)動(dòng)態(tài)表名的項(xiàng)目實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一、水平分表

  • 當(dāng)業(yè)務(wù)需求的數(shù)據(jù)量過(guò)大時(shí),一個(gè)表格存儲(chǔ)數(shù)據(jù)會(huì)非常之多,故時(shí)長(zhǎng)采用水平分表的方式來(lái)減少每張表的數(shù)據(jù)量即是提升查詢數(shù)據(jù)庫(kù)時(shí)的效率。
  • 水平分表時(shí),各表的結(jié)構(gòu)完全一樣,表名不同。
  • 例如:這里我們建了10張user表,每張表的結(jié)構(gòu)完全一致,表名由0~9。
  • 表中包含有id和name屬性且都采用varchar的存儲(chǔ)類型。
  • 為什么id沒(méi)有采用int自增的形式?
  • 大型項(xiàng)目極有可能采用分布式數(shù)據(jù)庫(kù),若采用自增的方式,會(huì)導(dǎo)致id重復(fù)。且id也不一定只是由純數(shù)字組成,id不由數(shù)據(jù)庫(kù)自主生成后,可在后臺(tái)代碼中是使用工具類進(jìn)行id生成。

在這里插入圖片描述

在這里插入圖片描述

二、項(xiàng)目實(shí)現(xiàn)

目錄結(jié)構(gòu)

不需要的文件我已經(jīng)手動(dòng)馬賽克,避免干擾。
簡(jiǎn)單以一個(gè)用戶信息的新增和查詢為例子。

在這里插入圖片描述

pom.xml

本次使用mybatis+mybatis-plus為例。

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

        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

application.yaml

server:
  port: 9090
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
    username: root
    password: root

mybatis-plus:
  mapper-locations: classpath:mybatis/*.xml #mapper位置
  type-aliases-package: com/example/demo/po #設(shè)置別名,類名的小寫

工具類

R返回類

package com.example.demo.utils;

import com.example.demo.utils.inter.ResultCode;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;


@Data
public class R<T> {

  private Boolean success;

  private Integer code;

  private String message;

  private T data;


  public R() {
  }

  public static <T> R<T> ok(){
      R<T> r = new R<>();
      r.setSuccess(true);
      r.setCode(ResultCode.SUCCESS);
      r.setMessage("成功");
      return r;
  }
  public static <T> R<T> error() {
      R<T> r = new R<>();
      r.setSuccess(false);
      r.setCode(ResultCode.ERROR);
      r.setMessage("失敗");
      return r;
  }

  public R<T> success(Boolean success) {
      this.setSuccess(success);
      return this;
  }

  public R<T> message(String message) {
      this.setMessage(message);
      return this;
  }

  public R<T> code(Integer code) {
      this.setCode(code);
      return this;
  }

  public void setData(T data) {
      this.data = data;
  }

  public R<T> data(T data) {
      this.setData(data);
      return this;
  }

  public R<T> setReLoginData() {
      Map<String, Integer> resultMap = new HashMap<>();
      resultMap.put("code", -100);
      this.data((T) resultMap);
      return this;
  }

  public R<T> setErrorCode(Integer errorCode) {
      Map<String, Integer> resultMap = new HashMap<>();
      resultMap.put("errorCode", errorCode);
      this.data((T) resultMap);
      return this;
  }
}

通過(guò)封裝的返回類來(lái)實(shí)現(xiàn)數(shù)據(jù)的返回,同時(shí)可以自定義返回code(各種錯(cuò)誤碼),便于項(xiàng)目規(guī)范即管理。

ResultCode:返回碼

package com.example.demo.utils.inter;

public interface ResultCode {
    Integer SUCCESS = 2000;

    Integer ERROR = 3000;
}

TableNameUtil:根據(jù)自己定義的規(guī)則獲取表名

這里可以通過(guò)字符串拼接,實(shí)現(xiàn)user_0~user_9的返回。
數(shù)據(jù)存儲(chǔ)規(guī)則: id最后一個(gè)數(shù)字為0即對(duì)應(yīng)user_0,同理9對(duì)應(yīng)user_9。

package com.example.demo.utils;

import org.springframework.stereotype.Component;

@Component
public class TableNameUtil {

    public String getUserTableName(String id){
        return "user_"+id.substring(id.length()-1);
    }
}

IdUtil:根據(jù)自己定義的規(guī)則生成唯一ID

這里的生成規(guī)則是通過(guò)UUID+隨機(jī)0~ 9的數(shù)字來(lái)實(shí)現(xiàn)唯一ID的生成。大型項(xiàng)目一般會(huì)有一個(gè)專門由于生成唯一序列號(hào)的服務(wù)器~。

package com.example.demo.utils;
import org.springframework.stereotype.Component;
import java.util.UUID;

@Component
public class IdUtil {

    public synchronized String generatorUserId(){
        return UUID.randomUUID()+String.valueOf(Math.random()*10);
    }
}

實(shí)體類

po類(Persistent Object )

package com.example.demo.po;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

@Data
@TableName("user_0")//mybatis-plus匹配一張表即可,因?yàn)樗斜淼慕Y(jié)構(gòu)完全一致。
public class User implements Serializable {
    @TableId
    private String id;

    private String name;
}

dto類(Data Transfer Object)

注: 用例比較簡(jiǎn)單,沒(méi)有幾個(gè)參數(shù),實(shí)際時(shí)新增和查詢可能都會(huì)封裝許多參數(shù)。
UserIn: 新增User時(shí)用于傳遞數(shù)據(jù),id由后臺(tái)生成,前端傳輸數(shù)據(jù)時(shí)就不必存在id字段。

package com.example.demo.po.dto;

import lombok.Data;

@Data
public class UserIn {
    private String name;
}

QueryUserId:查詢時(shí)使用

package com.example.demo.po.dto;

import lombok.Data;

@Data
public class QueryUserId {
    private String id;
}

Mapper層

UserMapper

package com.example.demo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.po.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface UserMapper extends BaseMapper<User> {
//這里只是簡(jiǎn)單定義了兩個(gè)接口,本打算寫個(gè)批量插入的,
//但是這必須要求批量插入時(shí)的所有表的id最后一位數(shù)字是相同的(即是同一張表),
//這里不符合,因?yàn)檫@里是在插入時(shí)隨機(jī)生成的,就和循環(huán)單獨(dú)插入一樣了~
    void insertUser(@Param("tableName") String tableName, @Param("user") User user);

    User selectUserById(@Param("tableName") String tableName, @Param("id") String id);
}

UserMapper.xml

與UserMapper相綁定,通過(guò)@Param指定傳參后xml中進(jìn)行調(diào)用時(shí)的名稱。
動(dòng)態(tài)表名的實(shí)現(xiàn)也是通過(guò)傳參實(shí)現(xiàn)的,這里直接傳遞參數(shù)"tableName"讓xml進(jìn)行獲取。
注: 這里使用${tableName}而不使用#{tableNaem}是因?yàn)樵谑褂?進(jìn)行預(yù)加載時(shí),由于此時(shí)未能獲取tableName,即無(wú)法確定具體的表格,預(yù)加載會(huì)報(bào)錯(cuò)。
不錯(cuò)的博客,詳細(xì)介紹

<?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 namespace="com.example.demo.mapper.UserMapper">
    <insert id="insertUser" parameterType="com.example.demo.po.User">
        insert into ${tableName}(id, name) values (#{user.id}, #{user.name});
    </insert>
    <select id="selectUserById" parameterType="java.lang.String" resultType="com.example.demo.po.User">
        select * from ${tableName} where id = '${id}'
    </select>
</mapper>

Service層

package com.example.demo.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.po.User;

public interface UserService extends IService<User> {

    void insertUser(User user);

    User selectUserById(String id);
}

impl實(shí)現(xiàn)類

package com.example.demo.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.mapper.UserMapper;
import com.example.demo.po.User;
import com.example.demo.service.UserService;
import com.example.demo.utils.IdUtil;
import com.example.demo.utils.TableNameUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private IdUtil idUtil;

    @Resource
    private TableNameUtil tableNameUtil;

    @Override
    public void insertUser(User user) {
        String id = idUtil.generatorUserId();//生成Id
        user.setId(id);
        String tableName = tableNameUtil.getUserTableName(id);//根據(jù)id獲取表名
        baseMapper.insertUser(tableName,user);
    }

    @Override
    public User selectUserById(String id) {
        String tableName = tableNameUtil.getUserTableName(id);
        return baseMapper.selectUserById(tableName, id);
    }
}

Controller層

package com.example.demo.controller;

import com.example.demo.po.User;
import com.example.demo.po.dto.UserIn;
import com.example.demo.service.UserService;
import com.example.demo.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @PostMapping("/insertUser")
    public R insertUser(@RequestBody UserIn userIn){
        User user = new User();
        user.setName(userIn.getName());
        userService.insertUser(user);
        return R.ok();
    }

    @GetMapping("/selectUserById")
    public R selectUserById(@RequestBody String id){
        User user = userService.selectUserById(id);
        return R.ok().data(user);
    }
}

過(guò)程及結(jié)果截圖展示

通過(guò)Apifox調(diào)用接口

在這里插入圖片描述

創(chuàng)建用戶User

使用自動(dòng)生成數(shù)據(jù),結(jié)果返回成功

在這里插入圖片描述

…多輸入些數(shù)據(jù)…查看數(shù)據(jù)庫(kù)中數(shù)據(jù)

在這里插入圖片描述

在這里插入圖片描述

… id查詢用戶

在這里插入圖片描述

測(cè)試成功

三、擴(kuò)展

還可以在xml中通過(guò)調(diào)用Java方法來(lái)實(shí)現(xiàn)生成表名的操作,這里就不需要mapper傳遞tableName參數(shù)了,但是需要用于獲取tableName的參數(shù)。在學(xué)習(xí)中遇到這種方式,做個(gè)記錄。
這種方式比較特殊,一般很少使用。

UserMapper新增

    void insertUserI(@Param("user") User user);
    
    User selectUserByIdI(@Param("id") String id);

UserMapper.xml新增

    <insert id="insertUserI" parameterType="com.example.demo.po.User">
        insert into "${@com.example.demo.utils.TableNameUtil@getUserTableName(id)}"(id, name) values (#{user.id}, #{user.name});
    </insert>
    <select id="selectUserByIdI" parameterType="java.lang.String" resultType="com.example.demo.po.User">
        select * from "${@com.example.demo.utils.TableNameUtil@getUserTableName(id)}" where id = '${id}'
    </select>
    或通過(guò)bind標(biāo)簽進(jìn)行綁定
    <insert id="insertUserI" parameterType="com.example.demo.po.User">
        <bind name="tableName" value="@com.example.demo.utils.TableNameUtil@getUserTableName(id)"/>
        insert into ${tableName}(id, name) values (#{user.id}, #{user.name});
    </insert>
    <select id="selectUserByIdI" parameterType="java.lang.String" resultType="com.example.demo.po.User">
        <bind name="tableName" value="@com.example.demo.utils.TableNameUtil@getUserTableName(id)"/>
        select * from ${tableName} where id = '${id}'
    </select>

Service層新增

    void insertUserI(@Param("user") User user);

    User selectUserByIdI(@Param("id") String id);

Controller層新增

    @PostMapping("/insertUserI")
    public R insertUserI(@RequestBody UserIn userIn){
        User user = new User();
        user.setName(userIn.getName());
        userService.insertUser(user);
        log.info("insertUserI OK");
        return R.ok();
    }

    @GetMapping("/selectUserByIdI")
    public R selectUserByIdI(@RequestBody QueryUserId queryUserId){
        User user = userService.selectUserById(queryUserId.getId());
        log.info("selectUserByIdI :"+user.toString());
        return R.ok().data(user);
    }

過(guò)程及結(jié)果截圖展示

調(diào)用insertUserI創(chuàng)建新用戶

在這里插入圖片描述

日志打印

在這里插入圖片描述

數(shù)據(jù)庫(kù)中數(shù)據(jù)

在這里插入圖片描述

調(diào)用selectUserByIdI進(jìn)行查詢

在這里插入圖片描述

日志查看

在這里插入圖片描述

關(guān)于xml調(diào)用Java方法時(shí)是否能獲取對(duì)應(yīng)參數(shù)

這里在getUserTableName方法下輸出了一下id

在這里插入圖片描述

在這里插入圖片描述

 到此這篇關(guān)于mybatis水平分表實(shí)現(xiàn)動(dòng)態(tài)表名的項(xiàng)目實(shí)例的文章就介紹到這了,更多相關(guān)mybatis 動(dòng)態(tài)表名內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論