<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot 整合 Sharding-JDBC 分庫分表

          共 51477字,需瀏覽 103分鐘

           ·

          2021-04-22 13:32

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

            作者 |  陳彥斌

          來源 |  urlify.cn/F73IBj

          導(dǎo)讀

            分庫分表的技術(shù)有:數(shù)據(jù)庫中間件Mycat(點(diǎn)我直達(dá)),當(dāng)當(dāng)網(wǎng)開源的Sharding-JDBC;我們公司用的也是sharding-jdbc,自己也搭建一個(gè)完整的項(xiàng)目,直接可以拿來用。下面附源碼(CRUD,分頁,事務(wù)等都已測試過)

          技術(shù)棧

          • SpringBoot 2.3.9

          • sharding-jdbc-core 2.0.3 (官網(wǎng)地址:點(diǎn)我直達(dá))

          • druid

          • mybatis-plus

          • lombok

          • mybatis | mybatisplus 分頁功能

          • 統(tǒng)一異常處理器

          項(xiàng)目結(jié)構(gòu)

          pom.xml

          <?xml version="1.0" encoding="UTF-8"?>
          <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
              <modelVersion>4.0.0</modelVersion>
              <parent>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-parent</artifactId>
                  <version>2.3.9.RELEASE</version>
                  <relativePath/> <!-- lookup parent from repository -->
              </parent>
              <groupId>com.ybchen</groupId>
              <artifactId>springboot-sharding</artifactId>
              <version>0.0.1-SNAPSHOT</version>
              <name>springboot-sharding</name>
              <description>Demo project for Spring Boot</description>
              <properties>
                  <java.version>1.8</java.version>
                  <maven.compiler.target>1.8</maven.compiler.target>
                  <maven.compiler.source>1.8</maven.compiler.source>
                  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
              </properties>
              <dependencies>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-web</artifactId>
                  </dependency>

                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-test</artifactId>
                      <scope>test</scope>
                      <exclusions>
                          <exclusion>
                              <groupId>org.junit.vintage</groupId>
                              <artifactId>junit-vintage-engine</artifactId>
                          </exclusion>
                      </exclusions>
                  </dependency>
                  <!--sharding-->
                  <dependency>
                      <groupId>io.shardingjdbc</groupId>
                      <artifactId>sharding-jdbc-core</artifactId>
                      <version>2.0.3</version>
                  </dependency>
                  <!--mysql-->
                  <dependency>
                      <groupId>mysql</groupId>
                      <artifactId>mysql-connector-java</artifactId>
                  </dependency>
                  <!--druid-->
                  <dependency>
                      <groupId>com.alibaba</groupId>
                      <artifactId>druid</artifactId>
                      <version>1.2.5</version>
                  </dependency>
                  <!--mybatisplus-->
                  <dependency>
                      <groupId>com.baomidou</groupId>
                      <artifactId>mybatis-plus-boot-starter</artifactId>
                      <version>3.4.1</version>
                  </dependency>
                  <!--mybatis pagehelper分頁插件-->
                  <dependency>
                      <groupId>com.github.pagehelper</groupId>
                      <artifactId>pagehelper</artifactId>
                      <version>5.2.0</version>
                  </dependency>
                  <!--lombok-->
                  <dependency>
                      <groupId>org.projectlombok</groupId>
                      <artifactId>lombok</artifactId>
                      <version>1.18.20</version>
                  </dependency>
              </dependencies>

              <build>
                  <plugins>
                      <plugin>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-maven-plugin</artifactId>
                      </plugin>
                  </plugins>
                  <resources>
                      <resource>
                          <directory>src/main/java</directory>
                          <includes>
                              <include>**/*.xml</include>
                          </includes>
                      </resource>
                      <resource>
                          <directory>src/main/resources</directory>
                      </resource>
                  </resources>
              </build>
          </project>

          logback-spring.xml

          <?xml version="1.0" encoding="UTF-8"?>
          <!-- 日志級(jí)別從低到高分為TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果設(shè)置為WARN,則低于WARN的信息都不會(huì)輸出 -->
          <!-- scan:當(dāng)此屬性設(shè)置為true時(shí),配置文件如果發(fā)生改變,將會(huì)被重新加載,默認(rèn)值為true -->
          <!-- scanPeriod:設(shè)置監(jiān)測配置文件是否有修改的時(shí)間間隔,如果沒有給出時(shí)間單位,默認(rèn)單位是毫秒。當(dāng)scan為true時(shí),此屬性生效。默認(rèn)的時(shí)間間隔為1分鐘。 -->
          <!-- debug:當(dāng)此屬性設(shè)置為true時(shí),將打印出logback內(nèi)部日志信息,實(shí)時(shí)查看logback運(yùn)行狀態(tài)。默認(rèn)值為false。 -->
          <configuration  scan="true" scanPeriod="10 seconds">

              <contextName>logback</contextName>
              <!-- name的值是變量的名稱,value的值時(shí)變量定義的值。通過定義的值會(huì)被插入到logger上下文中。定義變量后,可以使“${}”來使用變量。 -->
              <property name="log.path" value="applog/" />
              <property name="log.name" value="springboot-sharding"/>
              <!--控制臺(tái)打印格式-->
              <property name="CONSOLE_LOG_PATTERN_FILE" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %C:%M:%L [%thread] %-5level %msg%n"/>
              <!--debug文件打印格式-->
              <property name="DEBUG_LOG_PATTERN_FILE" value="%d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n"/>

              <!-- 彩色日志 -->
              <!-- 彩色日志依賴的渲染類 -->
              <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
              <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
              <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
              <!-- 彩色日志格式 -->
              <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>


              <!--輸出到控制臺(tái)-->
              <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
                  <!--此日志appender是為開發(fā)使用,只配置最底級(jí)別,控制臺(tái)輸出的日志級(jí)別是大于或等于此級(jí)別的日志信息-->
                  <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                      <level>debug</level>
                  </filter>
                  <encoder>
                      <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
                      <!-- 設(shè)置字符集 -->
                      <charset>UTF-8</charset>
                  </encoder>
              </appender>


              <!--輸出到文件-->
              <!-- 時(shí)間滾動(dòng)輸出 level為 INFO 日志 -->
              <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
                  <!-- 正在記錄的日志文件的路徑及文件名 -->
                  <file>${log.path}/${log.name}/${log.name}_info.log</file>
                  <!--日志文件輸出格式-->
                  <encoder>
                      <pattern>${CONSOLE_LOG_PATTERN_FILE}</pattern>
                      <charset>UTF-8</charset>
                  </encoder>
                  <!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
                  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                      <!-- 每天日志歸檔路徑以及格式 -->
                      <fileNamePattern>${log.path}/${log.name}/info/${log.name}-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                          <maxFileSize>100MB</maxFileSize>
                      </timeBasedFileNamingAndTriggeringPolicy>
                      <!--日志文件保留天數(shù)-->
                      <maxHistory>15</maxHistory>
                  </rollingPolicy>
                  <!-- 此日志文件只記錄info級(jí)別的 -->
                  <filter class="ch.qos.logback.classic.filter.LevelFilter">
                      <level>info</level>
                      <onMatch>ACCEPT</onMatch>
                      <onMismatch>DENY</onMismatch>
                  </filter>
              </appender>

              <!-- 時(shí)間滾動(dòng)輸出 level為 debug 日志 -->
              <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
                  <!-- 正在記錄的日志文件的路徑及文件名 -->
                  <file>${log.path}/${log.name}/${log.name}_debug.log</file>
                  <!--日志文件輸出格式-->
                  <encoder>
                      <pattern>${DEBUG_LOG_PATTERN_FILE}</pattern>
                      <charset>UTF-8</charset> <!-- 此處設(shè)置字符集 -->
                  </encoder>
                  <!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
                  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                      <fileNamePattern>${log.path}/${log.name}/debug/${log.name}-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                          <maxFileSize>100MB</maxFileSize>
                      </timeBasedFileNamingAndTriggeringPolicy>
                      <!--日志文件保留天數(shù)-->
                      <maxHistory>15</maxHistory>
                  </rollingPolicy>
                  <!-- 此日志文件只記錄DEBUG級(jí)別的 -->
                  <filter class="ch.qos.logback.classic.filter.LevelFilter">
                      <level>DEBUG</level>
                      <onMatch>ACCEPT</onMatch>
                      <onMismatch>DENY</onMismatch>
                  </filter>
              </appender>

              <!-- 時(shí)間滾動(dòng)輸出 level為 ERROR 日志 -->
              <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
                  <!-- 正在記錄的日志文件的路徑及文件名 -->
                  <file>${log.path}/${log.name}/${log.name}_error.log</file>
                  <!--日志文件輸出格式-->
                  <encoder>
                      <pattern>${CONSOLE_LOG_PATTERN_FILE}</pattern>
                      <charset>UTF-8</charset> <!-- 此處設(shè)置字符集 -->
                  </encoder>
                  <!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
                  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                      <fileNamePattern>${log.path}/${log.name}/error/${log.name}-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                          <maxFileSize>100MB</maxFileSize>
                      </timeBasedFileNamingAndTriggeringPolicy>
                      <!--日志文件保留天數(shù)-->
                      <maxHistory>15</maxHistory>
                  </rollingPolicy>
                  <!-- 此日志文件只記錄ERROR級(jí)別的 -->
                  <filter class="ch.qos.logback.classic.filter.LevelFilter">
                      <level>ERROR</level>
                      <onMatch>ACCEPT</onMatch>
                      <onMismatch>DENY</onMismatch>
                  </filter>
              </appender>

              <root level="info">
                  <appender-ref ref="CONSOLE" />
                  <appender-ref ref="INFO_FILE" />
                  <appender-ref ref="DEBUG_FILE" />
                  <appender-ref ref="ERROR_FILE" />
              </root>
              <logger name="com.ybchen.mapper" level="DEBUG"/>
              <logger name="com.ybchen" level="DEBUG"/>
          </configuration>

          application.properties

          server.port=9999
          # ds0
          ds0.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
          ds0.datasource.url=jdbc:mysql://localhost:3306/online_education?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
          ds0.datasource.username=root
          ds0.datasource.password=root
          # ds1
          ds1.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
          ds1.datasource.url=jdbc:mysql://localhost:3306/online_education1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
          ds1.datasource.username=root
          ds1.datasource.password=root

          UserMapper.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 namespace="com.ybchen.mapper.UserMapper">
              <select id="all" resultType="com.ybchen.domain.UserDO">
                  SELECT * FROM t_user
              </select>
              <insert id="add" parameterType="com.ybchen.domain.UserDO">
                  INSERT INTO `t_user` (`id`, `user_name`, `age`, `create_time`, `tags`) VALUES (#{id}, #{userName}, #{age}, #{createTime}, #{tags})
              </insert>
              <update id="update" parameterType="com.ybchen.domain.UserDO">
                  update t_user set user_name=#{userName} where id=#{id}
              </update>
              <delete id="delete">
                  delete from t_user where id=#{id}
              </delete>
          </mapper>

          SpringBootShardingApplication.java

          package com.ybchen;

          import org.mybatis.spring.annotation.MapperScan;
          import org.springframework.boot.SpringApplication;
          import org.springframework.boot.autoconfigure.SpringBootApplication;
          import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
          import org.springframework.transaction.annotation.EnableTransactionManagement;

          //忽略自動(dòng)裝配DataSource
          @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
          //掃描Mapper
          @MapperScan("com.ybchen.mapper")
          //開啟事務(wù)
          @EnableTransactionManagement
          public class SpringbootShardingApplication {

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

          }

          DataSourceConfig.java

          package com.ybchen;

          import com.alibaba.druid.filter.Filter;
          import com.alibaba.druid.filter.stat.StatFilter;
          import com.alibaba.druid.pool.DruidDataSource;
          import com.baomidou.mybatisplus.annotation.DbType;
          import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
          import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
          import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
          import com.github.pagehelper.PageInterceptor;
          import com.google.common.collect.Lists;
          import groovy.util.logging.Slf4j;
          import io.shardingjdbc.core.api.ShardingDataSourceFactory;
          import io.shardingjdbc.core.api.config.ShardingRuleConfiguration;
          import io.shardingjdbc.core.api.config.TableRuleConfiguration;
          import io.shardingjdbc.core.api.config.strategy.InlineShardingStrategyConfiguration;
          import org.apache.ibatis.plugin.Interceptor;
          import org.apache.ibatis.session.SqlSessionFactory;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          import org.springframework.core.env.Environment;
          import org.springframework.core.io.Resource;
          import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
          import org.springframework.jdbc.datasource.DataSourceTransactionManager;
          import org.springframework.transaction.annotation.EnableTransactionManagement;

          import javax.sql.DataSource;
          import java.sql.SQLException;
          import java.util.*;

          /**
           * @Description:配置參考鏈接:https://shardingsphere.apache.org/document/legacy/3.x/document/cn/manual/sharding-jdbc/configuration/config-java/
           * @Author:chenyanbin
           * @Date:2021/4/15 上午11:44
           * @Versiion:1.0
           */
          @Configuration
          @EnableTransactionManagement
          @Slf4j
          public class DataSourceConfig {
              @Autowired
              private Environment env;

              @Bean
              public Filter statFilter() {
                  StatFilter filter = new StatFilter();
                  filter.setSlowSqlMillis(5000);
                  filter.setLogSlowSql(true);
                  filter.setMergeSql(true);
                  return filter;
              }

              @Bean("sqlSessionFactory")
              SqlSessionFactory sqlSessionFactory(
              ) throws Exception {
                  final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
                  //設(shè)置數(shù)據(jù)源
                  sessionFactory.setDataSource(dataSource());
                  //設(shè)置分頁
                  sessionFactory.setPlugins(new Interceptor[]{mybatisPlusInterceptor(), pageInterceptor()});
                  //mapper掃描路徑
                  Resource[] r1 = new PathMatchingResourcePatternResolver()
                          .getResources("classpath*:com/ybchen/mapper/xml/*.xml");
                  Resource[] r2 = new PathMatchingResourcePatternResolver()
                          .getResources("classpath*:mapper/*.xml");
                  List<Resource> list = new ArrayList<>();
                  list.addAll(Arrays.asList(r1));
                  list.addAll(Arrays.asList(r2));
                  sessionFactory.setMapperLocations(list.toArray(new Resource[list.size()]));
                  return sessionFactory.getObject();
              }

              //事務(wù)管理
              @Bean
              public DataSourceTransactionManager transactitonManager(@Autowired DataSource dataSource) {
                  return new DataSourceTransactionManager(dataSource);
              }

              //mybatis 分頁
              public PageInterceptor pageInterceptor() {
                  PageInterceptor pi = new PageInterceptor();
                  Properties p = new Properties();
                  //當(dāng)該參數(shù)設(shè)置為 true 時(shí),pageNum<=0 時(shí)會(huì)查詢第一頁, pageNum>pages(超過總數(shù)時(shí)),會(huì)查詢最后一頁
                  p.setProperty("reasonable""true");
                  pi.setProperties(p);
                  return pi;
              }

              //mybatis plus分頁
              public MybatisPlusInterceptor mybatisPlusInterceptor() {
                  MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
                  mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
                  return mybatisPlusInterceptor;
              }

              @Bean
              public DataSource dataSource() throws SQLException {
                  ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
                  //添加表
                  shardingRuleConfig.getTableRuleConfigs().add(tUserTableRuleConfiguration());
                  Properties properties = new Properties();
                  //是否開啟SQL顯示,默認(rèn)值: false
          //        properties.setProperty("sql.show""true");
                  return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, new HashMap<>(), properties);
              }

              /**
               * 表分片規(guī)則配置對(duì)象,表:t_user
               * 參考鏈接:https://shardingsphere.apache.org/document/legacy/3.x/document/cn/manual/sharding-jdbc/configuration/config-java/
               *
               * @return
               */
              TableRuleConfiguration tUserTableRuleConfiguration() {
                  TableRuleConfiguration result = new TableRuleConfiguration();
                  //邏輯表名稱
                  result.setLogicTable("t_user");
                  //由數(shù)據(jù)源名 + 表名組成,以小數(shù)點(diǎn)分隔。多個(gè)表以逗號(hào)分隔,支持inline表達(dá)式。缺省表示使用已知數(shù)據(jù)源與邏輯表名稱生成數(shù)據(jù)節(jié)點(diǎn)。用于廣播表(即每個(gè)庫中都需要一個(gè)同樣的表用于關(guān)聯(lián)查詢,多為字典表)或只分庫不分表且所有庫的表結(jié)構(gòu)完全一致的情況
                  result.setActualDataNodes("ds${0..1}.t_user");
                  //分片列名稱
                  final String shardingColumn = "tags";
                  //分片算法行表達(dá)式,需符合groovy語法,表達(dá)式參考:https://shardingsphere.apache.org/document/legacy/3.x/document/cn/features/sharding/other-features/inline-expression/
                  final String algorithmExpression = "ds${tags%2}";
                  //ShardingStrategyConfiguration的實(shí)現(xiàn)類,用于配置行表達(dá)式分片策略。
                  result.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration(shardingColumn, algorithmExpression));
                  //自增列名稱,缺省表示不適用自增主鍵生成器
          //        result.setKeyGeneratorColumnName("id");
                  return result;
              }

              Map<String, DataSource> createDataSourceMap() {
                  Map<String, DataSource> result = new HashMap<>();
                  result.put("ds0", dataSource_0());
                  result.put("ds1", dataSource_1());
                  return result;
              }

              /**
               * 數(shù)據(jù)源-0
               *
               * @return
               */
              public DataSource dataSource_0() {
                  DruidDataSource dataSource = new DruidDataSource();
                  dataSource.setDriverClassName(env.getProperty("ds0.datasource.driver-class-name"));
                  dataSource.setUrl(env.getProperty("ds0.datasource.url"));
                  dataSource.setUsername(env.getProperty("ds0.datasource.username"));
                  dataSource.setPassword(env.getProperty("ds0.datasource.password"));
                  dataSource.setProxyFilters(Lists.newArrayList(statFilter()));
                  //每個(gè)分區(qū)最大的連接數(shù)
                  dataSource.setMaxActive(20);
                  //每個(gè)分區(qū)最小的連接數(shù)
                  dataSource.setMinIdle(5);
                  return dataSource;
              }

              /**
               * 數(shù)據(jù)源-1
               *
               * @return
               */
              public DataSource dataSource_1() {
                  DruidDataSource dataSource = new DruidDataSource();
                  dataSource.setDriverClassName(env.getProperty("ds1.datasource.driver-class-name"));
                  dataSource.setUrl(env.getProperty("ds1.datasource.url"));
                  dataSource.setUsername(env.getProperty("ds1.datasource.username"));
                  dataSource.setPassword(env.getProperty("ds1.datasource.password"));
                  dataSource.setProxyFilters(Lists.newArrayList(statFilter()));
                  //每個(gè)分區(qū)最大的連接數(shù)
                  dataSource.setMaxActive(20);
                  //每個(gè)分區(qū)最小的連接數(shù)
                  dataSource.setMinIdle(5);
                  return dataSource;
              }
          }

          GlobalExceptions.java

          package com.ybchen.exception;

          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;
          import org.springframework.web.bind.annotation.ControllerAdvice;
          import org.springframework.web.bind.annotation.ExceptionHandler;
          import org.springframework.web.bind.annotation.ResponseBody;

          /**
           * @ClassName:GlobalExceptiions
           * @Description:全局異常
           * @Author:chenyb
           * @Date:2021/4/15 上午11:44
           * @Versiion:1.0
           */
          @ControllerAdvice
          public class GlobalExceptions {
              private final Logger logger = LoggerFactory.getLogger(getClass());

              @ExceptionHandler(value = Exception.class)
              @ResponseBody
              public Object handle(Exception ex) {
                  logger.error("「 全局異常 」 ===============》{}", ex);
                  return "「 全局異常 」錯(cuò)誤信息:"+ex.getMessage();
              }
          }

          UserDO.java

          package com.ybchen.domain;

          import java.util.Date;

          /**
           * @Description:mybatis方式實(shí)體類
           * @Author:chenyanbin
           * @Date:2021/4/16 上午9:47
           * @Versiion:1.0
           */
          public class UserDO {
              private String id;
              private String userName;
              private Integer age;
              private Date createTime;
              private Integer tags;

              public String getId() {
                  return id;
              }

              public void setId(String id) {
                  this.id = id;
              }

              public String getUserName() {
                  return userName;
              }

              public void setUserName(String userName) {
                  this.userName = userName;
              }

              public Integer getAge() {
                  return age;
              }

              public void setAge(Integer age) {
                  this.age = age;
              }

              public Date getCreateTime() {
                  return createTime;
              }

              public void setCreateTime(Date createTime) {
                  this.createTime = createTime;
              }

              public Integer getTags() {
                  return tags;
              }

              public void setTags(Integer tags) {
                  this.tags = tags;
              }

              @Override
              public String toString() {
                  return "UserDO{" +
                          "id='" + id + '\'' +
                          ", userName='
          " + userName + '\'' +
                          "
          , age=" + age +
                          "
          , createTime=" + createTime +
                          "
          , tags=" + tags +
                          '}';
              }
          }

          UserMybatisDO.java

          package com.ybchen.domain;

          import com.baomidou.mybatisplus.annotation.TableField;
          import com.baomidou.mybatisplus.annotation.TableId;
          import com.baomidou.mybatisplus.annotation.TableName;

          import java.util.Date;

          /**
           * @Description:mybatis plus方式實(shí)體類
           * @Author:chenyanbin
           * @Date:2021/4/16 上午9:47
           * @Versiion:1.0
           */
          @TableName("t_user")
          public class UserMybatisDO {
              @TableId(value = "id")
              private String id;
              @TableField("user_name")
              private String userName;
              @TableField("age")
              private Integer age;
              @TableField("create_time")
              private Date createTime;
              @TableField("tags")
              private Integer tags;

              public String getId() {
                  return id;
              }

              public void setId(String id) {
                  this.id = id;
              }

              public String getUserName() {
                  return userName;
              }

              public void setUserName(String userName) {
                  this.userName = userName;
              }

              public Integer getAge() {
                  return age;
              }

              public void setAge(Integer age) {
                  this.age = age;
              }

              public Date getCreateTime() {
                  return createTime;
              }

              public void setCreateTime(Date createTime) {
                  this.createTime = createTime;
              }

              public Integer getTags() {
                  return tags;
              }

              public void setTags(Integer tags) {
                  this.tags = tags;
              }

              @Override
              public String toString() {
                  return "UserMybatisDO{" +
                          "id='" + id + '\'' +
                          ", userName='
          " + userName + '\'' +
                          "
          , age=" + age +
                          "
          , createTime=" + createTime +
                          "
          , tags=" + tags +
                          '}';
              }
          }

          UserMapper.java

          package com.ybchen.mapper;

          import com.ybchen.domain.UserDO;

          import java.util.List;

          public interface UserMapper {
              //查詢
              List<UserDO> all();

              //添加
              Integer add(UserDO userDO);

              //更新
              Integer update(UserDO userDO);

              //刪除
              Integer delete(String id);
          }

          UserMybatisPlusMapper.java

          package com.ybchen.mapper;

          import com.baomidou.mybatisplus.core.mapper.BaseMapper;
          import com.ybchen.domain.UserMybatisDO;

          public interface UserMybatisPlusMapper extends BaseMapper<UserMybatisDO> {
          }

          UserService.java

          package com.ybchen.service;

          import com.ybchen.domain.UserDO;
          import com.ybchen.domain.UserMybatisDO;

          import java.util.List;

          /**
           * @Description:
           * @Author:chenyanbin
           * @Date:2021/4/15 下午4:52
           * @Versiion:1.0
           */
          public interface UserService {
              //mybatis 查詢
              List<UserDO> all();

              //mybatisplus 查詢
              List<UserMybatisDO> allMybatisPlus();

              //添加
              Integer add(UserDO userDO);

              //更新
              Integer update(UserDO userDO);

              //刪除
              Integer delete(String id);
          }

          UserServiceImpl.java

          package com.ybchen.service.impl;

          import com.baomidou.mybatisplus.core.metadata.IPage;
          import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
          import com.github.pagehelper.PageHelper;
          import com.ybchen.domain.UserDO;
          import com.ybchen.domain.UserMybatisDO;
          import com.ybchen.mapper.UserMapper;
          import com.ybchen.mapper.UserMybatisPlusMapper;
          import com.ybchen.service.UserService;
          import lombok.extern.slf4j.Slf4j;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Service;
          import org.springframework.transaction.annotation.Transactional;

          import java.time.LocalDateTime;
          import java.util.List;
          import java.util.UUID;

          /**
           * @Description:
           * @Author:chenyanbin
           * @Date:2021/4/15 下午4:53
           * @Versiion:1.0
           */
          @Service
          @Slf4j
          public class UserServiceImpl implements UserService {
              @Autowired
              UserMapper userMapper;
              @Autowired
              UserMybatisPlusMapper userMybatisPlusMapper;

              @Override
              public List<UserDO> all() {
                  log.info("---info----");
                  log.debug("----debug----");
                  log.error("----error----");
                  //mybatis 分頁
                  PageHelper.startPage(4, 3);
                  return userMapper.all();
              }

              @Override
              public List<UserMybatisDO> allMybatisPlus() {
                  //mybatis plus 分頁
                  int start = 4;
                  int end = 3;
                  IPage<UserMybatisDO> page = new Page<>(start, end);
                  return userMybatisPlusMapper.selectPage(page, null).getRecords();
              }

              @Override
              //開啟事務(wù)
              @Transactional
              public Integer add(UserDO userDO) {
                  userDO.setId(UUID.randomUUID().toString().replace("-"""));
                  userDO.setTags(LocalDateTime.now().getSecond());
                  userMapper.add(userDO);
                  //模擬事務(wù)失敗
                  int num = 1 / 0;
                  userDO.setAge(99);
                  userDO.setId(UUID.randomUUID().toString().replace("-"""));
                  return userMapper.add(userDO);
              }

              @Override
              public Integer update(UserDO userDO) {
                  return userMapper.update(userDO);
              }

              @Override
              public Integer delete(String id) {
                  return userMapper.delete(id);
              }
          }

          UserController.java

          package com.ybchen.controller;

          import com.ybchen.domain.UserDO;
          import com.ybchen.service.UserService;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.web.bind.annotation.*;

          /**
           * @Description:
           * @Author:chenyanbin
           * @Date:2021/4/15 下午4:52
           * @Versiion:1.0
           */
          @RestController
          public class UserController {
              @Autowired
              private UserService userService;

              @PostMapping("all")
              public Object all() {
                  return userService.all();
              }

              @PostMapping("allMybatisPlus")
              public Object allMybatisPlus() {
                  return userService.allMybatisPlus();
              }

              @PostMapping("add")
              public Object add(@RequestBody UserDO userDO) {
                  return userService.add(userDO);
              }

              @PostMapping("update")
              public Object update(@RequestBody UserDO userDO) {
                  return userService.update(userDO);
              }

              @GetMapping("delete")
              public Object delete(@RequestParam("id") String id) {
                  return userService.delete(id);
              }
          }

          數(shù)據(jù)庫





          粉絲福利:Java從入門到入土學(xué)習(xí)路線圖

          ??????

          ??長按上方微信二維碼 2 秒


          感謝點(diǎn)贊支持下哈 

          瀏覽 63
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  乱伦大杂烩视频 | 一级操逼图 | 超碰人妻中文字幕 | 女人18毛片AAA片水真多 女人18片毛片90分钟免费 | 国产suv精品一区二区三区 |