mybatis在指定库建表_Spring Boot:实现MyBatis动态创建表

本文介绍了如何在Spring Boot项目中结合MyBatis动态创建和操作数据库表。通过一个用户日志表配置的案例,展示了如何根据配置信息生成用户特定的日志存储表,并提供了接口进行操作。案例包括项目初始化、数据库表创建、MyBatis配置、数据源配置、接口编写等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

综合概述

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

实现案例

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

生成项目模板

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

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

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

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

创建数据库表

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

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

脚本文件

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

springboot.sql

-- ----------------------------

-- Table structure foruser_log_config-- ----------------------------DROP TABLE IF EXISTS `user_log_config`;

CREATE TABLE `user_log_config` (

`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',

`name` varchar(50) NOT NULL COMMENT '用户名',

`table_name` varchar(150) DEFAULT NULL COMMENT '用户对应的日志存储表',

PRIMARY KEY (`id`),

UNIQUE KEY `name` (`name`)

) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8 COMMENT='用户日志表配置';-- ----------------------------

-- Table structure foruser_log-- ----------------------------DROP TABLE IF EXISTS `user_log`;

CREATE TABLE `user_log` (

`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',

`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',

`operation` varchar(50) DEFAULT NULL COMMENT '用户操作',

`method` varchar(200) DEFAULT NULL COMMENT '请求方法',

`params` varchar(5000) DEFAULT NULL COMMENT '请求参数',

`time` bigint(20) NOT NULL COMMENT '执行时长(毫秒)',

`ip` varchar(64) DEFAULT NULL COMMENT 'IP地址',

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=2897 DEFAULT CHARSET=utf8 COMMENT='用户操作日志';

添加相关依赖

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

pom.xml

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.1.5.RELEASE

com.louis.springboot

demo

0.0.1-SNAPSHOT

demo

Demo project for Spring Boot

1.8

org.springframework.boot

spring-boot-starter

org.springframework.boot

spring-boot-starter-web

io.springfox

springfox-swagger2

2.9.2

io.springfox

springfox-swagger-ui

2.9.2

org.mybatis.spring.boot

mybatis-spring-boot-starter

2.0.0

mysql

mysql-connector-java

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-maven-plugin

src/main/java

**/sqlmap/*.xml

false

src/main/resources

**/*.*

true

添加配置类

1. 添加swagger 配置

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

SwaggerConfig.java

package com.louis.springboot.demo.config;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.ApiInfoBuilder;

import springfox.documentation.builders.PathSelectors;

import springfox.documentation.builders.RequestHandlerSelectors;

import springfox.documentation.service.ApiInfo;

import springfox.documentation.spi.DocumentationType;

import springfox.documentation.spring.web.plugins.Docket;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration

@EnableSwagger2public classSwaggerConfig {

@BeanpublicDocket createRestApi(){return newDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())

.select()

.apis(RequestHandlerSelectors.any())

.paths(PathSelectors.any()).build();

}privateApiInfo apiInfo(){return newApiInfoBuilder()

.title("SpringBoot API Doc")

.description("This is a restful api document of Spring Boot.")

.version("1.0")

.build();

}

}

2.添加MyBatis配置

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

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

MybatisConfig.java

package com.louis.springboot.demo.config;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;

import org.mybatis.spring.SqlSessionFactoryBean;

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

@Configuration

@MapperScan("com.louis.springboot.**.dao") //扫描DAO

public classMybatisConfig {

@AutowiredprivateDataSource dataSource;

@BeanpublicSqlSessionFactory sqlSessionFactory() throws Exception {

SqlSessionFactoryBean sessionFactory= newSqlSessionFactoryBean();

sessionFactory.setDataSource(dataSource);

sessionFactory.setTypeAliasesPackage("com.louis.springboot.**.model"); //扫描Model

PathMatchingResourcePatternResolver resolver= newPathMatchingResourcePatternResolver();

sessionFactory.setMapperLocations(resolver.getResources("classpath*:**/sqlmap/*.xml")); //扫描映射文件

returnsessionFactory.getObject();

}

}

3.添加数据源配置

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

注意:

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

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

application.yml

server:

port:8080spring:

datasource:

driverClassName: com.mysql.cj.jdbc.Driver

url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8

username: root

password:123456

生成MyBatis模块

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

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

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

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

UserLogConfig.java

package com.louis.springboot.demo.model;public classUserLogConfig {privateLong id;privateString name;privateString tableName;publicLong getId() {returnid;

}public voidsetId(Long id) {this.id =id;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name = name == null ? null: name.trim();

}publicString getTableName() {returntableName;

}public voidsetTableName(String tableName) {this.tableName = tableName == null ? null: tableName.trim();

}

}

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

UserLogConfigMapper.java

package com.louis.springboot.demo.dao;

import java.util.List;

import com.louis.springboot.demo.model.UserLogConfig;public interfaceUserLogConfigMapper {intdeleteByPrimaryKey(Long id);intinsert(UserLogConfig record);intinsertSelective(UserLogConfig record);

UserLogConfig selectByPrimaryKey(Long id);intupdateByPrimaryKeySelective(UserLogConfig record);intupdateByPrimaryKey(UserLogConfig record);public ListselectAll();

}

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

UserLogConfigMapper.xml

id, name, table_name

select

fromuser_log_configwhere id = #{id,jdbcType=BIGINT}

deletefromuser_log_configwhere id = #{id,jdbcType=BIGINT}

insert into user_log_config (id, name, table_name

)

values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{tableName,jdbcType=VARCHAR}

)

insert into user_log_config

id,

name,

table_name,

#{id,jdbcType=BIGINT},

#{name,jdbcType=VARCHAR},

#{tableName,jdbcType=VARCHAR},

update user_log_config

name= #{name,jdbcType=VARCHAR},

table_name= #{tableName,jdbcType=VARCHAR},

where id = #{id,jdbcType=BIGINT}

update user_log_configset name = #{name,jdbcType=VARCHAR},

table_name= #{tableName,jdbcType=VARCHAR}where id = #{id,jdbcType=BIGINT}

select

fromuser_log_config

编写UserLogConfig的服务接口。

UserLogConfigService.java

package com.louis.springboot.demo.service;

import java.util.List;

import com.louis.springboot.demo.model.UserLogConfig;public interfaceUserLogConfigService {/**

* 保存用户日志配置

* @return*/

voidsave(UserLogConfig userLogConfig);/**

* 查找全部用户日志配置

* @return*/ListfindAll();

}

编写UserLogConfig的服务实现类。

UserLogConfigServiceImpl.java

package com.louis.springboot.demo.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import com.louis.springboot.demo.dao.UserLogConfigMapper;

import com.louis.springboot.demo.model.UserLogConfig;

import com.louis.springboot.demo.service.UserLogConfigService;

@Servicepublic classUserLogConfigServiceImpl implements UserLogConfigService {

@AutowiredprivateUserLogConfigMapper userLogConfigMapper;

@Overridepublic voidsave(UserLogConfig userLogConfig) {if(userLogConfig.getId() != null && !"".equals(userLogConfig.getId())) {//更新

userLogConfigMapper.updateByPrimaryKeySelective(userLogConfig);

}else{//插入

userLogConfigMapper.insertSelective(userLogConfig);

}

}

@Overridepublic ListfindAll() {returnuserLogConfigMapper.selectAll();

}

}

编写UserLogConfig的控制器。

UserLogConfigController.java

package com.louis.springboot.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import com.louis.springboot.demo.model.UserLogConfig;

import com.louis.springboot.demo.service.UserLogConfigService;

@RestController

@RequestMapping("user/log/config")public classUserLogConfigController {

@AutowiredprivateUserLogConfigService userLogConfigService;

@PostMapping(value="/save")publicObject save(@RequestBody UserLogConfig userLogConfig) {

userLogConfigService.save(userLogConfig);return 1;

}

@GetMapping(value="/findAll")publicObject findAll() {returnuserLogConfigService.findAll();

}

}

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

UserLog.java

package com.louis.springboot.demo.model;public classUserLog {privateLong id;privateString userName;privateString operation;privateString method;private String params;privateLong time;privateString ip;publicLong getId() {returnid;

}public voidsetId(Long id) {this.id =id;

}publicString getUserName() {returnuserName;

}public voidsetUserName(String userName) {this.userName = userName == null ? null: userName.trim();

}publicString getOperation() {returnoperation;

}public voidsetOperation(String operation) {this.operation = operation == null ? null: operation.trim();

}publicString getMethod() {returnmethod;

}public voidsetMethod(String method) {this.method = method == null ? null: method.trim();

}publicString getParams() {return params;

}public void setParams(String params) {this.params = params == null ? null : params.trim();

}publicLong getTime() {returntime;

}public voidsetTime(Long time) {this.time =time;

}publicString getIp() {returnip;

}public voidsetIp(String ip) {this.ip = ip == null ? null: ip.trim();

}

}

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

UserLogMapper.java

package com.louis.springboot.demo.dao;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import com.louis.springboot.demo.model.UserLog;public interfaceUserLogMapper {int deleteByPrimaryKey(@Param("tableName")String tableName, @Param("id")Long id);int insert(@Param("tableName")String tableName, @Param("userLog") UserLog userLog);int insertSelective(@Param("tableName")String tableName, @Param("userLog") UserLog record);

UserLog selectByPrimaryKey(@Param("tableName")String tableName, @Param("id")Long id);int updateByPrimaryKeySelective(@Param("tableName")String tableName, @Param("userLog") UserLog record);int updateByPrimaryKey(@Param("tableName")String tableName, @Param("userLog") UserLog record);/**

* 查找全部

* @param tableName

* @return*/List selectAll(@Param("tableName")String tableName);/**

* 是否存在表

* @param tableName

* @return*/

int existTable(@Param("tableName")String tableName);/**

* 删除表

* @param tableName

* @return*/

int dropTable(@Param("tableName")String tableName);/**

* 创建表

* @param tableName

* @return*/

int createTable(@Param("tableName")String tableName);

}

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

UserLogMapper.xml

id, user_name, operation, method,params, time, ip

select

from${tableName}where id = #{id,jdbcType=BIGINT}

deletefrom${tableName}where id = #{id,jdbcType=BIGINT}

insert into ${tableName} (id, user_name, operation,

method,params, time,

ip)

values (#{id,jdbcType=BIGINT}, #{userName,jdbcType=VARCHAR}, #{operation,jdbcType=VARCHAR},

#{method,jdbcType=VARCHAR}, #{params,jdbcType=VARCHAR}, #{time,jdbcType=BIGINT},

#{ip,jdbcType=VARCHAR})

insert into ${tableName}

id,

user_name,

operation,

method,

params,

time,

ip,

#{id,jdbcType=BIGINT},

#{userName,jdbcType=VARCHAR},

#{operation,jdbcType=VARCHAR},

#{method,jdbcType=VARCHAR},

#{params,jdbcType=VARCHAR},

#{time,jdbcType=BIGINT},

#{ip,jdbcType=VARCHAR},

update ${tableName}

user_name= #{userName,jdbcType=VARCHAR},

operation= #{operation,jdbcType=VARCHAR},

method= #{method,jdbcType=VARCHAR},

params = #{params,jdbcType=VARCHAR},

time= #{time,jdbcType=BIGINT},

ip= #{ip,jdbcType=VARCHAR},

where id = #{id,jdbcType=BIGINT}

update ${tableName}set user_name = #{userName,jdbcType=VARCHAR},

operation= #{operation,jdbcType=VARCHAR},

method= #{method,jdbcType=VARCHAR},params = #{params,jdbcType=VARCHAR},

time= #{time,jdbcType=BIGINT},

ip= #{ip,jdbcType=VARCHAR}where id = #{id,jdbcType=BIGINT}

select

from${tableName}

select count(*)frominformation_schema.TABLESwhere table_name=#{tableName}

DROP TABLE IF EXISTS ${tableName}

CREATE TABLE ${tableName} (

`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',

`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',

`operation` varchar(50) DEFAULT NULL COMMENT '用户操作',

`method` varchar(200) DEFAULT NULL COMMENT '请求方法',

`params` varchar(5000) DEFAULT NULL COMMENT '请求参数',

`time` bigint(20) NOT NULL COMMENT '执行时长(毫秒)',

`ip` varchar(64) DEFAULT NULL COMMENT 'IP地址',

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=2897 DEFAULT CHARSET=utf8 COMMENT='用户操作日志';

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

UserLogService.java

package com.louis.springboot.demo.service;

import java.util.List;

import com.louis.springboot.demo.model.UserLog;public interfaceUserLogService {/**

* 保存用户日志

* @return*/

voidsave(String tableName, UserLog userLog);/**

* 查找全部用户日志

* @return*/ListfindAll(String tableName);

}

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

UserLogServiceImpl.java

package com.louis.springboot.demo.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import com.louis.springboot.demo.dao.UserLogMapper;

import com.louis.springboot.demo.model.UserLog;

import com.louis.springboot.demo.service.UserLogService;

@Servicepublic classUserLogServiceImpl implements UserLogService {

@AutowiredprivateUserLogMapper userLogMapper;

@Overridepublic voidsave(String tableName, UserLog userLog) {//插入

userLogMapper.insertSelective(tableName, userLog);

}

@Overridepublic ListfindAll(String tableName) {returnuserLogMapper.selectAll(tableName);

}

}

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

UserLog.java

package com.louis.springboot.demo.model;public classUserLog {privateLong id;privateString userName;privateString operation;privateString method;private String params;privateLong time;privateString ip;privateString tableName;publicLong getId() {returnid;

}public voidsetId(Long id) {this.id =id;

}publicString getUserName() {returnuserName;

}public voidsetUserName(String userName) {this.userName = userName == null ? null: userName.trim();

}publicString getOperation() {returnoperation;

}public voidsetOperation(String operation) {this.operation = operation == null ? null: operation.trim();

}publicString getMethod() {returnmethod;

}public voidsetMethod(String method) {this.method = method == null ? null: method.trim();

}publicString getParams() {return params;

}public void setParams(String params) {this.params = params == null ? null : params.trim();

}publicLong getTime() {returntime;

}public voidsetTime(Long time) {this.time =time;

}publicString getIp() {returnip;

}public voidsetIp(String ip) {this.ip = ip == null ? null: ip.trim();

}publicString getTableName() {returntableName;

}public voidsetTableName(String tableName) {this.tableName =tableName;

}

}

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

UserLogController.java

package com.louis.springboot.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import com.louis.springboot.demo.model.UserLog;

import com.louis.springboot.demo.service.UserLogService;

@RestController

@RequestMapping("user/log")public classUserLogController {

@AutowiredprivateUserLogService userLogService;

@PostMapping(value="/save")publicObject save(@RequestBody UserLog userLog) {

String tableName=userLog.getTableName();

userLogService.save(tableName, userLog);return 1;

}

@GetMapping(value="/findAll")publicObject findAll(String tableName) {returnuserLogService.findAll(tableName);

}

}

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

UserLogConfigServiceImpl.java

package com.louis.springboot.demo.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import com.louis.springboot.demo.dao.UserLogConfigMapper;

import com.louis.springboot.demo.dao.UserLogMapper;

import com.louis.springboot.demo.model.UserLogConfig;

import com.louis.springboot.demo.service.UserLogConfigService;

@Servicepublic classUserLogConfigServiceImpl implements UserLogConfigService {

@AutowiredprivateUserLogConfigMapper userLogConfigMapper;

@AutowiredprivateUserLogMapper userLogMapper;

@Overridepublic voidsave(UserLogConfig userLogConfig) {//插入

userLogConfigMapper.insertSelective(userLogConfig);//添加配置时,创建日志存储表

String tableName =userLogConfig.getTableName();if(userLogMapper.existTable(tableName) > 0) {

userLogMapper.dropTable(tableName);

}

userLogMapper.createTable(tableName);

}

@Overridepublic ListfindAll() {returnuserLogConfigMapper.selectAll();

}

}

编译测试运行

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

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

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

{"id": 1,"name": "xiaoming","tableName": "xiaoming"}

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

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

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

{"id": 1,"ip": "139.123.123.100","method": "save","operation": "save","params": "string name","tableName": "xiaoming","time": 0,"userName": "xiaoming"}

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

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

参考资料

相关导航

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值