综合概述

在有些应用场景中,我们会有需要动态创建和操作表的需求。比如因为单表数据存储量太大而采取分表存储的情况,又或者是按日期生成日志表存储系统日志等等。这个时候就需要我们动态的生成和操作数据库表了。而我们都知道,以往我们使用MyBatis是需要提前生成包括Model,Mapper和XML映射文件的,显然因为动态生成和操作表的需求一开始表都是不存在的,所以也就不能直接通过MyBatis连接数据库来生成我们的数据访问层代码并用来访问数据库了。还好MyBatis提供了动态SQL,我们可以通过动态SQL,传入表名等信息然组装成建表和操作语句,接下来,我们就通过一个具体的案例来了解一下。

实现案例

先说一下我们要实现的案例,本案例中每个用户都会有一个自己日志表,其中的user_log_config表就是用户名和对应的日志表配置,每次往这个表添加配置的时候,系统就会根据配置信息给该用户生成一个日志存储表,表名是获取日志配置表里配置的表名称,并统一提供对这个日志表的操作接口。本教程案例基于 Spring Boot + Mybatis + MySQL 实现。

生成项目模板

为方便我们初始化项目,Spring Boot给我们提供一个项目模板生成网站。

1.  打开浏览器,访问:https://start.spring.io/

2.  根据页面提示,选择构建工具,开发语言,项目信息等。

3.  点击 Generate the project,生成项目模板,生成之后会将压缩包下载到本地。

4.  使用IDE导入项目,我这里使用Eclipse,通过导入Maven项目的方式导入。

创建数据库表

这里使用MySQL数据库,版本是8.0.16,在项目根目录下新建db目录,然后在其中编写一个数据库脚本文件。

在MySQL数据库新建一个springboot数据库,然后在此数据库中执行下面的脚本创建项目相关的表。

脚本文件

SQL脚本内容,注意,这里的user_log并不需要用到,事实上,user_log就是我们要生成的表结构,但为了一会儿MyBatis代码的生成,先创建一下,具体后续会讲到。

springboot.sql

  1. -- ----------------------------
  2. -- Table structure for user_log_config
  3. -- ----------------------------
  4. DROP TABLE IF EXISTS `user_log_config`;
  5. CREATE TABLE `user_log_config` (
  6. `id` bigint() NOT NULL AUTO_INCREMENT COMMENT '编号',
  7. `name` varchar() NOT NULL COMMENT '用户名',
  8. `table_name` varchar() DEFAULT NULL COMMENT '用户对应的日志存储表',
  9. PRIMARY KEY (`id`),
  10. UNIQUE KEY `name` (`name`)
  11. ) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8 COMMENT='用户日志表配置';
  12. -- ----------------------------
  13. -- Table structure for user_log
  14. -- ----------------------------
  15. DROP TABLE IF EXISTS `user_log`;
  16. CREATE TABLE `user_log` (
  17. `id` bigint() NOT NULL AUTO_INCREMENT COMMENT '编号',
  18. `user_name` varchar() DEFAULT NULL COMMENT '用户名',
  19. `operation` varchar() DEFAULT NULL COMMENT '用户操作',
  20. `method` varchar() DEFAULT NULL COMMENT '请求方法',
  21. `params` varchar() DEFAULT NULL COMMENT '请求参数',
  22. `time` bigint() NOT NULL COMMENT '执行时长(毫秒)',
  23. `ip` varchar() DEFAULT NULL COMMENT 'IP地址',
  24. PRIMARY KEY (`id`)
  25. ) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8 COMMENT='用户操作日志';

添加相关依赖

需要添加Spring Boot,Mybatis,MySQL,Swagger相关依赖。Swagger方便用来测试接口。

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.1..RELEASE</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.louis.springboot</groupId>
  12. <artifactId>demo</artifactId>
  13. <version>0.0.-SNAPSHOT</version>
  14. <name>demo</name>
  15. <description>Demo project for Spring Boot</description>
  16.  
  17. <properties>
  18. <java.version>1.8</java.version>
  19. </properties>
  20.  
  21. <dependencies>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter</artifactId>
  25. </dependency>
  26. <!-- web -->
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-web</artifactId>
  30. </dependency>
  31. <!-- swagger -->
  32. <dependency>
  33. <groupId>io.springfox</groupId>
  34. <artifactId>springfox-swagger2</artifactId>
  35. <version>2.9.</version>
  36. </dependency>
  37. <dependency>
  38. <groupId>io.springfox</groupId>
  39. <artifactId>springfox-swagger-ui</artifactId>
  40. <version>2.9.</version>
  41. </dependency>
  42. <!-- mybatis -->
  43. <dependency>
  44. <groupId>org.mybatis.spring.boot</groupId>
  45. <artifactId>mybatis-spring-boot-starter</artifactId>
  46. <version>2.0.</version>
  47. </dependency>
  48. <!-- mysql -->
  49. <dependency>
  50. <groupId>mysql</groupId>
  51. <artifactId>mysql-connector-java</artifactId>
  52. </dependency>
  53. <dependency>
  54. <groupId>org.springframework.boot</groupId>
  55. <artifactId>spring-boot-starter-test</artifactId>
  56. <scope>test</scope>
  57. </dependency>
  58. </dependencies>
  59.  
  60. <build>
  61. <plugins>
  62. <plugin>
  63. <groupId>org.springframework.boot</groupId>
  64. <artifactId>spring-boot-maven-plugin</artifactId>
  65. </plugin>
  66. </plugins>
  67. <!-- 打包时拷贝MyBatis的映射文件 -->
  68. <resources>
  69. <resource>
  70. <directory>src/main/java</directory>
  71. <includes>
  72. <include>**/sqlmap/*.xml</include>
  73. </includes>
  74. <filtering>false</filtering>
  75. </resource>
  76. <resource>
  77. <directory>src/main/resources</directory>
  78. <includes>
  79. <include>**/*.*</include>
  80. </includes>
  81. <filtering>true</filtering>
  82. </resource>
  83. </resources>
  84. </build>
  85.  
  86. </project>

添加配置类

1. 添加swagger 配置

添加一个swagger 配置类,在工程下新建 config 包并添加一个 SwaggerConfig 配置类。

SwaggerConfig.java

  1. package com.louis.springboot.demo.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import springfox.documentation.builders.ApiInfoBuilder;
  5. import springfox.documentation.builders.PathSelectors;
  6. import springfox.documentation.builders.RequestHandlerSelectors;
  7. import springfox.documentation.service.ApiInfo;
  8. import springfox.documentation.spi.DocumentationType;
  9. import springfox.documentation.spring.web.plugins.Docket;
  10. import springfox.documentation.swagger2.annotations.EnableSwagger2;
  11.  
  12. @Configuration
  13. @EnableSwagger2
  14. public class SwaggerConfig {
  15.  
  16. @Bean
  17. public Docket createRestApi(){
  18. return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
  19. .select()
  20. .apis(RequestHandlerSelectors.any())
  21. .paths(PathSelectors.any()).build();
  22. }
  23.  
  24. private ApiInfo apiInfo(){
  25. return new ApiInfoBuilder()
  26. .title("SpringBoot API Doc")
  27. .description("This is a restful api document of Spring Boot.")
  28. .version("1.0")
  29. .build();
  30. }
  31.  
  32. }

2.添加MyBatis配置

添加MyBatis配置类,配置相关扫描路径,包括DAO,Model,XML映射文件的扫描。

在config包下新建一个MyBatis配置类,MybatisConfig.java。

MybatisConfig.java

  1. package com.louis.springboot.demo.config;
  2. import javax.sql.DataSource;
  3.  
  4. import org.apache.ibatis.session.SqlSessionFactory;
  5. import org.mybatis.spring.SqlSessionFactoryBean;
  6. import org.mybatis.spring.annotation.MapperScan;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Configuration;
  10. import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
  11.  
  12. @Configuration
  13. @MapperScan("com.louis.springboot.**.dao") // 扫描DAO
  14. public class MybatisConfig {
  15. @Autowired
  16. private DataSource dataSource;
  17.  
  18. @Bean
  19. public SqlSessionFactory sqlSessionFactory() throws Exception {
  20. SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
  21. sessionFactory.setDataSource(dataSource);
  22. sessionFactory.setTypeAliasesPackage("com.louis.springboot.**.model"); // 扫描Model
  23.  
  24. PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
  25. sessionFactory.setMapperLocations(resolver.getResources("classpath*:**/sqlmap/*.xml")); // 扫描映射文件
  26.  
  27. return sessionFactory.getObject();
  28. }
  29. }

3.添加数据源配置

将application.properties文件改名为application.yml ,并在其中添加MySQL数据源连接信息。

注意:

这里需要首先创建一个MySQL数据库,并输入自己的用户名和密码。这里的数据库是springboot。

另外,如果你使用的是MySQL 5.x及以前版本,驱动配置driverClassName是com.mysql.jdbc.Driver。

application.yml

  1. server:
  2. port:
  3. spring:
  4. datasource:
  5. driverClassName: com.mysql.cj.jdbc.Driver
  6. url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8
  7. username: root
  8. password:

生成MyBatis模块

由于手动编写MyBatis的Model、DAO、XML映射文件比较繁琐,通常都会通过一些生成工具来生成。MyBatis官方也提供了生成工具(MyBaits Generator),另外还有一些基于官方基础上改进的第三方工具,比如MyBatis Plus就是国内提供的一款非常优秀的开源工具,网上相关教程比较多,这里就不再赘述了。

这里提供一些资料作为参考。

Mybatis Generator 官网:http://www.mybatis.org/generator/index.html

Mybatis Generator 教程:https://blog.csdn.net/testcs_dn/article/details/77881776

MyBatis Plus 官网: http://mp.baomidou.com/#/

MyBatis Plus 官网: http://mp.baomidou.com/#/quick-start

代码生成好之后,分別将MODEL、DAO、XML映射文件拷贝到相应的包里。

生成的Model,如下是user_log_config表对应的Model对象UserLogConfig。

UserLogConfig.java

  1. package com.louis.springboot.demo.model;
  2.  
  3. public class UserLogConfig {
  4. private Long id;
  5.  
  6. private String name;
  7.  
  8. private String tableName;
  9.  
  10. public Long getId() {
  11. return id;
  12. }
  13.  
  14. public void setId(Long id) {
  15. this.id = id;
  16. }
  17.  
  18. public String getName() {
  19. return name;
  20. }
  21.  
  22. public void setName(String name) {
  23. this.name = name == null ? null : name.trim();
  24. }
  25.  
  26. public String getTableName() {
  27. return tableName;
  28. }
  29.  
  30. public void setTableName(String tableName) {
  31. this.tableName = tableName == null ? null : tableName.trim();
  32. }
  33. }

打开Mapper,我们看到MyBatis Generator给我们默认生成了一些增删改查的方法,另外添加一个查询全部的方法。

UserLogConfigMapper.java

  1. package com.louis.springboot.demo.dao;
  2.  
  3. import java.util.List;
  4.  
  5. import com.louis.springboot.demo.model.UserLogConfig;
  6.  
  7. public interface UserLogConfigMapper {
  8. int deleteByPrimaryKey(Long id);
  9.  
  10. int insert(UserLogConfig record);
  11.  
  12. int insertSelective(UserLogConfig record);
  13.  
  14. UserLogConfig selectByPrimaryKey(Long id);
  15.  
  16. int updateByPrimaryKeySelective(UserLogConfig record);
  17.  
  18. int updateByPrimaryKey(UserLogConfig record);
  19.  
  20. public List<UserLogConfig> selectAll();
  21. }

在UserLogConfigMapper.xml中编写selectAll的SQL语句。

UserLogConfigMapper.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.louis.springboot.demo.dao.UserLogConfigMapper">
  4. <resultMap id="BaseResultMap" type="com.louis.springboot.demo.model.UserLogConfig">
  5. <id column="id" jdbcType="BIGINT" property="id" />
  6. <result column="name" jdbcType="VARCHAR" property="name" />
  7. <result column="table_name" jdbcType="VARCHAR" property="tableName" />
  8. </resultMap>
  9. <sql id="Base_Column_List">
  10. id, name, table_name
  11. </sql>
  12. <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
  13. select
  14. <include refid="Base_Column_List" />
  15. from user_log_config
  16. where id = #{id,jdbcType=BIGINT}
  17. </select>
  18. <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
  19. delete from user_log_config
  20. where id = #{id,jdbcType=BIGINT}
  21. </delete>
  22. <insert id="insert" parameterType="com.louis.springboot.demo.model.UserLogConfig">
  23. insert into user_log_config (id, name, table_name
  24. )
  25. values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{tableName,jdbcType=VARCHAR}
  26. )
  27. </insert>
  28. <insert id="insertSelective" parameterType="com.louis.springboot.demo.model.UserLogConfig">
  29. insert into user_log_config
  30. <trim prefix="(" suffix=")" suffixOverrides=",">
  31. <if test="id != null">
  32. id,
  33. </if>
  34. <if test="name != null">
  35. name,
  36. </if>
  37. <if test="tableName != null">
  38. table_name,
  39. </if>
  40. </trim>
  41. <trim prefix="values (" suffix=")" suffixOverrides=",">
  42. <if test="id != null">
  43. #{id,jdbcType=BIGINT},
  44. </if>
  45. <if test="name != null">
  46. #{name,jdbcType=VARCHAR},
  47. </if>
  48. <if test="tableName != null">
  49. #{tableName,jdbcType=VARCHAR},
  50. </if>
  51. </trim>
  52. </insert>
  53. <update id="updateByPrimaryKeySelective" parameterType="com.louis.springboot.demo.model.UserLogConfig">
  54. update user_log_config
  55. <set>
  56. <if test="name != null">
  57. name = #{name,jdbcType=VARCHAR},
  58. </if>
  59. <if test="tableName != null">
  60. table_name = #{tableName,jdbcType=VARCHAR},
  61. </if>
  62. </set>
  63. where id = #{id,jdbcType=BIGINT}
  64. </update>
  65. <update id="updateByPrimaryKey" parameterType="com.louis.springboot.demo.model.UserLogConfig">
  66. update user_log_config
  67. set name = #{name,jdbcType=VARCHAR},
  68. table_name = #{tableName,jdbcType=VARCHAR}
  69. where id = #{id,jdbcType=BIGINT}
  70. </update>
  71. <select id="selectAll" resultMap="BaseResultMap">
  72. select
  73. <include refid="Base_Column_List" />
  74. from user_log_config
  75. </select>
  76. </mapper>

编写UserLogConfig的服务接口。

UserLogConfigService.java

  1. package com.louis.springboot.demo.service;
  2. import java.util.List;
  3.  
  4. import com.louis.springboot.demo.model.UserLogConfig;
  5.  
  6. public interface UserLogConfigService {
  7.  
  8. /**
  9. * 保存用户日志配置
  10. * @return
  11. */
  12. void save(UserLogConfig userLogConfig);
  13.  
  14. /**
  15. * 查找全部用户日志配置
  16. * @return
  17. */
  18. List<UserLogConfig> findAll();
  19.  
  20. }

编写UserLogConfig的服务实现类。

UserLogConfigServiceImpl.java

  1. package com.louis.springboot.demo.service.impl;
  2. import java.util.List;
  3.  
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Service;
  6.  
  7. import com.louis.springboot.demo.dao.UserLogConfigMapper;
  8. import com.louis.springboot.demo.model.UserLogConfig;
  9. import com.louis.springboot.demo.service.UserLogConfigService;
  10.  
  11. @Service
  12. public class UserLogConfigServiceImpl implements UserLogConfigService {
  13.  
  14. @Autowired
  15. private UserLogConfigMapper userLogConfigMapper;
  16.  
  17. @Override
  18. public void save(UserLogConfig userLogConfig) {
  19. if(userLogConfig.getId() != null && !"".equals(userLogConfig.getId())) {
  20. // 更新
  21. userLogConfigMapper.updateByPrimaryKeySelective(userLogConfig);
  22. } else {
  23. // 插入
  24. userLogConfigMapper.insertSelective(userLogConfig);
  25. }
  26. }
  27.  
  28. @Override
  29. public List<UserLogConfig> findAll() {
  30. return userLogConfigMapper.selectAll();
  31. }
  32. }

编写UserLogConfig的控制器。

UserLogConfigController.java

  1. package com.louis.springboot.demo.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.PostMapping;
  5. import org.springframework.web.bind.annotation.RequestBody;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8.  
  9. import com.louis.springboot.demo.model.UserLogConfig;
  10. import com.louis.springboot.demo.service.UserLogConfigService;
  11.  
  12. @RestController
  13. @RequestMapping("user/log/config")
  14. public class UserLogConfigController {
  15.  
  16. @Autowired
  17. private UserLogConfigService userLogConfigService;
  18.  
  19. @PostMapping(value="/save")
  20. public Object save(@RequestBody UserLogConfig userLogConfig) {
  21. userLogConfigService.save(userLogConfig);
  22. return ;
  23. }
  24.  
  25. @GetMapping(value="/findAll")
  26. public Object findAll() {
  27. return userLogConfigService.findAll();
  28. }
  29. }

现在我们来讲解如何动态实现动态生成用户日志存储表(user_log的表结构),之前我们通过MyBatis生成了user_log的服务访问层代码,下面是Model类UserLog,你可以直接用或改个名称都行,我们这里就不改了。

UserLog.java

  1. package com.louis.springboot.demo.model;
  2.  
  3. public class UserLog {
  4. private Long id;
  5.  
  6. private String userName;
  7.  
  8. private String operation;
  9.  
  10. private String method;
  11.  
  12. private String params;
  13.  
  14. private Long time;
  15.  
  16. private String ip;
  17.  
  18. public Long getId() {
  19. return id;
  20. }
  21.  
  22. public void setId(Long id) {
  23. this.id = id;
  24. }
  25.  
  26. public String getUserName() {
  27. return userName;
  28. }
  29.  
  30. public void setUserName(String userName) {
  31. this.userName = userName == null ? null : userName.trim();
  32. }
  33.  
  34. public String getOperation() {
  35. return operation;
  36. }
  37.  
  38. public void setOperation(String operation) {
  39. this.operation = operation == null ? null : operation.trim();
  40. }
  41.  
  42. public String getMethod() {
  43. return method;
  44. }
  45.  
  46. public void setMethod(String method) {
  47. this.method = method == null ? null : method.trim();
  48. }
  49.  
  50. public String getParams() {
  51. return params;
  52. }
  53.  
  54. public void setParams(String params) {
  55. this.params = params == null ? null : params.trim();
  56. }
  57.  
  58. public Long getTime() {
  59. return time;
  60. }
  61.  
  62. public void setTime(Long time) {
  63. this.time = time;
  64. }
  65.  
  66. public String getIp() {
  67. return ip;
  68. }
  69.  
  70. public void setIp(String ip) {
  71. this.ip = ip == null ? null : ip.trim();
  72. }
  73. }

修改UserLogMapper,将原有的接口都加上tableName参数,传入表名以确定要操作的表。另外额外添加了三个跟建表有关的方法。

UserLogMapper.java

  1. package com.louis.springboot.demo.dao;
  2.  
  3. import java.util.List;
  4.  
  5. import org.apache.ibatis.annotations.Param;
  6.  
  7. import com.louis.springboot.demo.model.UserLog;
  8.  
  9. public interface UserLogMapper {
  10. int deleteByPrimaryKey(@Param("tableName")String tableName, @Param("id")Long id);
  11.  
  12. int insert(@Param("tableName")String tableName, @Param("userLog") UserLog userLog);
  13.  
  14. int insertSelective(@Param("tableName")String tableName, @Param("userLog") UserLog record);
  15.  
  16. UserLog selectByPrimaryKey(@Param("tableName")String tableName, @Param("id")Long id);
  17.  
  18. int updateByPrimaryKeySelective(@Param("tableName")String tableName, @Param("userLog") UserLog record);
  19.  
  20. int updateByPrimaryKey(@Param("tableName")String tableName, @Param("userLog") UserLog record);
  21.  
  22. /**
  23. * 查找全部
  24. * @param tableName
  25. * @return
  26. */
  27. List<UserLog> selectAll(@Param("tableName")String tableName);
  28.  
  29. /**
  30. * 是否存在表
  31. * @param tableName
  32. * @return
  33. */
  34. int existTable(@Param("tableName")String tableName);
  35. /**
  36. * 删除表
  37. * @param tableName
  38. * @return
  39. */
  40. int dropTable(@Param("tableName")String tableName);
  41. /**
  42. * 创建表
  43. * @param tableName
  44. * @return
  45. */
  46. int createTable(@Param("tableName")String tableName);
  47. }

修改UserLogMapper.xml,将原来用表名user_log的地方替换成${tableName},表示表名由外部方法传入。另外编写另外三个建表相关的语句,检查表是否存在和删除表的语句比较简单,创建表的只要把建表语句拷贝过来,然后把表名替换成${tableName}就行了。

UserLogMapper.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.louis.springboot.demo.dao.UserLogMapper">
  4. <resultMap id="BaseResultMap" type="com.louis.springboot.demo.model.UserLog">
  5. <id column="id" jdbcType="BIGINT" property="id" />
  6. <result column="user_name" jdbcType="VARCHAR" property="userName" />
  7. <result column="operation" jdbcType="VARCHAR" property="operation" />
  8. <result column="method" jdbcType="VARCHAR" property="method" />
  9. <result column="params" jdbcType="VARCHAR" property="params" />
  10. <result column="time" jdbcType="BIGINT" property="time" />
  11. <result column="ip" jdbcType="VARCHAR" property="ip" />
  12. </resultMap>
  13. <sql id="Base_Column_List">
  14. id, user_name, operation, method, params, time, ip
  15. </sql>
  16. <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
  17. select
  18. <include refid="Base_Column_List" />
  19. from ${tableName}
  20. where id = #{id,jdbcType=BIGINT}
  21. </select>
  22. <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
  23. delete from ${tableName}
  24. where id = #{id,jdbcType=BIGINT}
  25. </delete>
  26. <insert id="insert" parameterType="com.louis.springboot.demo.model.UserLog">
  27. insert into ${tableName} (id, user_name, operation,
  28. method, params, time,
  29. ip)
  30. values (#{id,jdbcType=BIGINT}, #{userName,jdbcType=VARCHAR}, #{operation,jdbcType=VARCHAR},
  31. #{method,jdbcType=VARCHAR}, #{params,jdbcType=VARCHAR}, #{time,jdbcType=BIGINT},
  32. #{ip,jdbcType=VARCHAR})
  33. </insert>
  34. <insert id="insertSelective" parameterType="com.louis.springboot.demo.model.UserLog">
  35. insert into ${tableName}
  36. <trim prefix="(" suffix=")" suffixOverrides=",">
  37. <if test="id != null">
  38. id,
  39. </if>
  40. <if test="userName != null">
  41. user_name,
  42. </if>
  43. <if test="operation != null">
  44. operation,
  45. </if>
  46. <if test="method != null">
  47. method,
  48. </if>
  49. <if test="params != null">
  50. params,
  51. </if>
  52. <if test="time != null">
  53. time,
  54. </if>
  55. <if test="ip != null">
  56. ip,
  57. </if>
  58. </trim>
  59. <trim prefix="values (" suffix=")" suffixOverrides=",">
  60. <if test="id != null">
  61. #{id,jdbcType=BIGINT},
  62. </if>
  63. <if test="userName != null">
  64. #{userName,jdbcType=VARCHAR},
  65. </if>
  66. <if test="operation != null">
  67. #{operation,jdbcType=VARCHAR},
  68. </if>
  69. <if test="method != null">
  70. #{method,jdbcType=VARCHAR},
  71. </if>
  72. <if test="params != null">
  73. #{params,jdbcType=VARCHAR},
  74. </if>
  75. <if test="time != null">
  76. #{time,jdbcType=BIGINT},
  77. </if>
  78. <if test="ip != null">
  79. #{ip,jdbcType=VARCHAR},
  80. </if>
  81. </trim>
  82. </insert>
  83. <update id="updateByPrimaryKeySelective" parameterType="com.louis.springboot.demo.model.UserLog">
  84. update ${tableName}
  85. <set>
  86. <if test="userName != null">
  87. user_name = #{userName,jdbcType=VARCHAR},
  88. </if>
  89. <if test="operation != null">
  90. operation = #{operation,jdbcType=VARCHAR},
  91. </if>
  92. <if test="method != null">
  93. method = #{method,jdbcType=VARCHAR},
  94. </if>
  95. <if test="params != null">
  96. params = #{params,jdbcType=VARCHAR},
  97. </if>
  98. <if test="time != null">
  99. time = #{time,jdbcType=BIGINT},
  100. </if>
  101. <if test="ip != null">
  102. ip = #{ip,jdbcType=VARCHAR},
  103. </if>
  104. </set>
  105. where id = #{id,jdbcType=BIGINT}
  106. </update>
  107. <update id="updateByPrimaryKey" parameterType="com.louis.springboot.demo.model.UserLog">
  108. update ${tableName}
  109. set user_name = #{userName,jdbcType=VARCHAR},
  110. operation = #{operation,jdbcType=VARCHAR},
  111. method = #{method,jdbcType=VARCHAR},
  112. params = #{params,jdbcType=VARCHAR},
  113. time = #{time,jdbcType=BIGINT},
  114. ip = #{ip,jdbcType=VARCHAR}
  115. where id = #{id,jdbcType=BIGINT}
  116. </update>
  117.  
  118. <select id="selectAll" resultMap="BaseResultMap">
  119. select
  120. <include refid="Base_Column_List" />
  121. from ${tableName}
  122. </select>
  123.  
  124. <select id="existTable" parameterType="String" resultType="Integer">
  125. select count(*)
  126. from information_schema.TABLES
  127. where table_name=#{tableName}
  128. </select>
  129.  
  130. <update id="dropTable">
  131. DROP TABLE IF EXISTS ${tableName}
  132. </update>
  133.  
  134. <update id="createTable" parameterType="String">
  135. CREATE TABLE ${tableName} (
  136. `id` bigint() NOT NULL AUTO_INCREMENT COMMENT '编号',
  137. `user_name` varchar() DEFAULT NULL COMMENT '用户名',
  138. `operation` varchar() DEFAULT NULL COMMENT '用户操作',
  139. `method` varchar() DEFAULT NULL COMMENT '请求方法',
  140. `params` varchar() DEFAULT NULL COMMENT '请求参数',
  141. `time` bigint() NOT NULL COMMENT '执行时长(毫秒)',
  142. `ip` varchar() DEFAULT NULL COMMENT 'IP地址',
  143. PRIMARY KEY (`id`)
  144. ) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8 COMMENT='用户操作日志';
  145. </update>
  146. </mapper>

编写用户日志的服务接口,包含一个保存方法和一个查询方法。

UserLogService.java

  1. package com.louis.springboot.demo.service;
  2. import java.util.List;
  3.  
  4. import com.louis.springboot.demo.model.UserLog;
  5.  
  6. public interface UserLogService {
  7.  
  8. /**
  9. * 保存用户日志
  10. * @return
  11. */
  12. void save(String tableName, UserLog userLog);
  13.  
  14. /**
  15. * 查找全部用户日志
  16. * @return
  17. */
  18. List<UserLog> findAll(String tableName);
  19.  
  20. }

编写用户日志的服务实现类,包含保存方法和查询方法的实现。

UserLogServiceImpl.java

  1. package com.louis.springboot.demo.service.impl;
  2. import java.util.List;
  3.  
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Service;
  6.  
  7. import com.louis.springboot.demo.dao.UserLogMapper;
  8. import com.louis.springboot.demo.model.UserLog;
  9. import com.louis.springboot.demo.service.UserLogService;
  10.  
  11. @Service
  12. public class UserLogServiceImpl implements UserLogService {
  13.  
  14. @Autowired
  15. private UserLogMapper userLogMapper;
  16.  
  17. @Override
  18. public void save(String tableName, UserLog userLog) {
  19. // 插入
  20. userLogMapper.insertSelective(tableName, userLog);
  21. }
  22.  
  23. @Override
  24. public List<UserLog> findAll(String tableName) {
  25. return userLogMapper.selectAll(tableName);
  26. }
  27. }

为了接口传表名方便,我们这里在UserLog类里加入一个tableName属性,用来给接口传入表名。

UserLog.java

  1. package com.louis.springboot.demo.model;
  2.  
  3. public class UserLog {
  4. private Long id;
  5.  
  6. private String userName;
  7.  
  8. private String operation;
  9.  
  10. private String method;
  11.  
  12. private String params;
  13.  
  14. private Long time;
  15.  
  16. private String ip;
  17.  
  18. private String tableName;
  19.  
  20. public Long getId() {
  21. return id;
  22. }
  23.  
  24. public void setId(Long id) {
  25. this.id = id;
  26. }
  27.  
  28. public String getUserName() {
  29. return userName;
  30. }
  31.  
  32. public void setUserName(String userName) {
  33. this.userName = userName == null ? null : userName.trim();
  34. }
  35.  
  36. public String getOperation() {
  37. return operation;
  38. }
  39.  
  40. public void setOperation(String operation) {
  41. this.operation = operation == null ? null : operation.trim();
  42. }
  43.  
  44. public String getMethod() {
  45. return method;
  46. }
  47.  
  48. public void setMethod(String method) {
  49. this.method = method == null ? null : method.trim();
  50. }
  51.  
  52. public String getParams() {
  53. return params;
  54. }
  55.  
  56. public void setParams(String params) {
  57. this.params = params == null ? null : params.trim();
  58. }
  59.  
  60. public Long getTime() {
  61. return time;
  62. }
  63.  
  64. public void setTime(Long time) {
  65. this.time = time;
  66. }
  67.  
  68. public String getIp() {
  69. return ip;
  70. }
  71.  
  72. public void setIp(String ip) {
  73. this.ip = ip == null ? null : ip.trim();
  74. }
  75.  
  76. public String getTableName() {
  77. return tableName;
  78. }
  79.  
  80. public void setTableName(String tableName) {
  81. this.tableName = tableName;
  82. }
  83.  
  84. }

编写服务控制器UserLogController并调用服务的相关接口。

UserLogController.java

  1. package com.louis.springboot.demo.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.PostMapping;
  5. import org.springframework.web.bind.annotation.RequestBody;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8.  
  9. import com.louis.springboot.demo.model.UserLog;
  10. import com.louis.springboot.demo.service.UserLogService;
  11.  
  12. @RestController
  13. @RequestMapping("user/log")
  14. public class UserLogController {
  15.  
  16. @Autowired
  17. private UserLogService userLogService;
  18.  
  19. @PostMapping(value="/save")
  20. public Object save(@RequestBody UserLog userLog) {
  21. String tableName = userLog.getTableName();
  22. userLogService.save(tableName, userLog);
  23. return ;
  24. }
  25.  
  26. @GetMapping(value="/findAll")
  27. public Object findAll(String tableName) {
  28. return userLogService.findAll(tableName);
  29. }
  30. }

修改UserLogConfigServiceImpl的save方法,实现在添加配置的时候生成对应的表。

UserLogConfigServiceImpl.java

  1. package com.louis.springboot.demo.service.impl;
  2. import java.util.List;
  3.  
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Service;
  6.  
  7. import com.louis.springboot.demo.dao.UserLogConfigMapper;
  8. import com.louis.springboot.demo.dao.UserLogMapper;
  9. import com.louis.springboot.demo.model.UserLogConfig;
  10. import com.louis.springboot.demo.service.UserLogConfigService;
  11.  
  12. @Service
  13. public class UserLogConfigServiceImpl implements UserLogConfigService {
  14.  
  15. @Autowired
  16. private UserLogConfigMapper userLogConfigMapper;
  17. @Autowired
  18. private UserLogMapper userLogMapper;
  19.  
  20. @Override
  21. public void save(UserLogConfig userLogConfig) {
  22. // 插入
  23. userLogConfigMapper.insertSelective(userLogConfig);
  24. // 添加配置时,创建日志存储表
  25. String tableName = userLogConfig.getTableName();
  26. if(userLogMapper.existTable(tableName) > ) {
  27. userLogMapper.dropTable(tableName);
  28. }
  29. userLogMapper.createTable(tableName);
  30. }
  31.  
  32. @Override
  33. public List<UserLogConfig> findAll() {
  34. return userLogConfigMapper.selectAll();
  35. }
  36. }

编译测试运行

1.  右键项目 -> Run as -> Maven install,开始执行Maven构建,第一次会下载Maven依赖,可能需要点时间,如果出现如下信息,就说明项目编译打包成功了。

2.  右键文件 DemoApplication.java -> Run as -> Java Application,开始启动应用,当出现如下信息的时候,就说明应用启动成功了,默认启动端口是8080。

3.  打开浏览器,访问:http://localhost:8080/swagger-ui.html,进入swagger接口文档界面。

4.  测试UserLogConfigMapper的save保存接口,输入以下参数进行测试。

  1. {
  2. "id": ,
  3. "name": "xiaoming",
  4. "tableName": "xiaoming"
  5. }

成功之后调UserLogConfigMapper的findAll接口,可以看到配置信息已经成功插入。

并且我们可以通过MySQL客户端查看到,在配置生成的同时生成了一个表名为xiaoming的数据库表。

5.  测试UserLogController的save保存接口,输入以下参数进行测试。

  1. {
  2. "id": ,
  3. "ip": "139.123.123.100",
  4. "method": "save",
  5. "operation": "save",
  6. "params": "string name",
  7. "tableName": "xiaoming",
  8. "time": ,
  9. "userName": "xiaoming"
  10. }

成功之后调UserLogController的findAll接口,可以看到配置信息已经成功插入。

测试到此,我们成功的保存了配置信息,并且动态创建了一个表,然后成功的往表里插入了一点数据,并通过接口查询出了插入的数据。

参考资料

MyBatis 官网:http://www.mybatis.org/mybatis-3/zh/index.html

MyBatis Generator 官网:http://www.mybatis.org/generator/index.html

MyBatis Plus 官网: http://mp.baomidou.com/#/quick-start

相关导航

Spring Boot 系列教程目录导航

Spring Boot:快速入门教程

Spring Boot:整合Swagger文档

Spring Boot:整合MyBatis框架

Spring Boot:实现MyBatis分页

源码下载

码云:https://gitee.com/liuge1988/spring-boot-demo.git


作者:朝雨忆轻尘
出处:https://www.cnblogs.com/xifengxiaoma/
版权所有,欢迎转载,转载请注明原文作者及出处。

Spring Boot:实现MyBatis动态创建表的更多相关文章

  1. MyBatis动态创建表

    转载请注明出处:https://www.cnblogs.com/Joanna-Yan/p/9187538.html 项目中业务需求的不同,有时候我们需要动态操作数据表(如:动态建表.操作表字段等).常 ...

  2. 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法

    相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...

  3. 使用intelliJ创建 spring boot + gradle + mybatis站点

    Spring boot作为快速入门是不错的选择,现在似乎没有看到大家写过spring boot + gradle + mybatis在intellij下的入门文章,碰巧.Net同事问到,我想我也可以写 ...

  4. spring boot + druid + mybatis + atomikos 多数据源配置 并支持分布式事务

    文章目录 一.综述 1.1 项目说明 1.2 项目结构 二.配置多数据源并支持分布式事务 2.1 导入基本依赖 2.2 在yml中配置多数据源信息 2.3 进行多数据源的配置 三.整合结果测试 3.1 ...

  5. Spring Boot 实战 —— MyBatis(注解版)使用方法

    原文链接: Spring Boot 实战 -- MyBatis(注解版)使用方法 简介 MyBatis 官网 是这么介绍它自己的: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过 ...

  6. spring boot集成mybatis(1)

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  7. Spring Boot 整合 Mybatis 实现 Druid 多数据源详解

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “清醒时做事,糊涂时跑步,大怒时睡觉,独处时思考” 本文提纲一.多数据源的应用场景二.运行 sp ...

  8. spring boot 整合 mybatis 以及原理

    同上一篇文章一样,spring boot 整合 mybatis过程中没有看见SqlSessionFactory,sqlsession(sqlsessionTemplate),就连在spring框架整合 ...

  9. 详解Spring Boot集成MyBatis的开发流程

    MyBatis是支持定制化SQL.存储过程以及高级映射的优秀的持久层框架,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集. spring Boot是能支持快速创建Spring应用的Java框 ...

随机推荐

  1. 买不起360随声wifi怎么办?这些都不是问题

    只需轻松一步,点击开启共享 软件下载地址:http://download.csdn.net/detail/lxq_xsyu/6384265 如果身边没有数据线怎么办?? 使用方法: 1.用手机连接Wi ...

  2. dp_Pku1887

    <span style="color:#000099;">/* A - 单纯dp 示例 Time Limit:1000MS Memory Limit:30000KB 6 ...

  3. prism behavior图示

    原文:prism behavior图示 怕以后丢失,还是发一下,看起来可能会比较乱

  4. Android显示gif格式图片

    大家知道,在Android中使用ImageView来显示gif格式的图片,我们无法得到gif格式图片该有的效果,它只会停在第一帧上,而不会继续.这时只能看到一张静态的图片,这里我们可以使用个简单的方法 ...

  5. 在IIS上部署.net core的webapi项目 以及502.5错误的两种解决方法

    首先要在服务器上面安装.net core https://github.com/dotnet/core/tree/master/release-notes/download-archives 这里面有 ...

  6. 【STL】关联容器 — hashtable

    C++ 11哈希表已被列入标准列.hashtable这是hash_set.hash_map.hash_multiset.hash_multimap的底层机制.即这四种容器中都包括一个hashtable ...

  7. ASP.NET Core 使用 EF 框架查询数据 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 使用 EF 框架查询数据 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 使用 EF 框架查询数据 上一章节我们学习了如何设置 ...

  8. Gradle 1.12 翻译——第九章 Groovy高速入口

    由于时间.没办法,做笔记和翻译的同时,大约Gradle用户指南.本博客不再做相关的注意事项.而仅仅翻译和本出版物中未翻译章节. 有关其他章节翻译请注意Github该项目:https://github. ...

  9. Debian7离线升级bash漏洞—然后修复方法

    ### 昨天还说的传说要又一次出补丁,今天就都出来了.基本操作一致就是測试结果不一样.继续修复 Debian7 wheezy版本号的bash漏洞,例如以下操作: 1.測试是否须要升级 # env x= ...

  10. Git Bash Cmd命令笔记

    生成ssh公钥ssh-keygen -t rsa -C "xxxxx@xxxxx.com" # 三次回车即可生成 ssh key 查看你的public keycat ~/.ssh/ ...