一、技术选型 SpringBoot2.4+、mybatisplus3.4+、Mysql5.7+、Redis3.0+ 二、编写目的 如果产品开发默认数据库采用mysql,但是当客户提出数据库需要采用sq
SpringBoot2.4+、mybatisplus3.4+、Mysql5.7+、Redis3.0+
如果产品开发默认数据库采用mysql,但是当客户提出数据库需要采用sqlserver或者oracle以及其他国产数据库时,程序中就不能出现方言性的sql语句,否则程序在个性化的sql上做不到数据库兼容,因此要想产品能兼容多种数据类型,则在编码时就要考虑将个性化的方言sql抽离出来。
实现思路:
(1)应用启动时要根据数据源知道当前链接的数据库类型,并存到全局变量
(2)根据数据库类型自动设置mybatis-plus分页方言
(3)个性化方言实现不要在主业务中耦合(如:if mysql … else if sqlserver…)
(4)个性化方言实现可以多种数据库类型复用(如mysql、mariadb可以用一种实现)
(5)个性化方言实现类能根据数据库类型自动注入
代码实现:
根据url获取数据库类型
import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;public class Dialect { private static DbType dbType = null; private static final String DB_URL = "spring.datasource.url"; public synchronized static DbType getDbType(){ if(dbType == null){ String url = PropUtil.getValue(DB_URL); dbType = JdbcUtils.getDbType(url); } return dbType; }}
自定义注解(实现方言实现的选择注入)
import com.baomidou.mybatisplus.annotation.DbType;import org.springframework.context.annotation.Conditional;import java.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME)@Target({ ElementType.TYPE, ElementType.METHOD })@Documented@Conditional(DbTypeCondition.class)public @interface ConditionalOnDbType { DbType[] types() default DbType.OTHER;}
注解条件实现
import com.baomidou.mybatisplus.annotation.DbType;import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;public class DbTypeCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { DbType[] dbTypes = (DbType[]) metadata.getAnnotationAttributes(ConditionalOnDbType.class.getName()).get("types"); for(DbType dbType : dbTypes){ if(Dialect.getDbType().equals(dbType)){ return true; } } return false; }}
分页方言配置
@Configurationpublic class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); //添加分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(Dialect.getDbType())); return interceptor; }}
数据源配置上注意驱动和URL的替换。
mysql配置
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://ip:3306/db?serverTimezone=Asia/Shanghai&useUnicode=true username: username passWord: password hikari: ## 最小空闲连接数 minimum-idle: 5 ## 最大连接数 maximum-pool-size: 20 ## 自动提交 auto-commit: true ## 连接池名称 pool-name: TmcHikariCP ## 超时时间(ms) connection-timeout: 30000
sqlserver配置
spring: datasource: driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver url: jdbc:sqlserver://ip:1433;databasename=db_schema;trustServerCertificate=true;integratedSecurity=false; username: username password: password hikari: ## 最小空闲连接数 minimum-idle: 5 ## 最大连接数 maximum-pool-size: 20 ## 自动提交 auto-commit: true ## 连接池名称 pool-name: TmcHikariCP ## 超时时间(ms) connection-timeout: 30000
方言抽离接口
public interface DialectService<T> { void conditon(QueryWrapper<T> queryWrapper, Map<String, Clazz> attrMap,Object k,Object v);}
Mysql方言实现
import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Service;import java.util.Map;@Slf4j@Service@ConditionalOnDbType(types = {DbType.MYSQL,DbType.MARIADB})public class MysqlFORMDataDialectServiceImpl implements FormDataDialectService<FormDataEntity> { @Override public void conditon(QueryWrapper<FormDataEntity> queryWrapper, Map<String, Clazz> attrMap, Object k, Object v) { try { //替换时间类型判断(时间查询为时间段) Clazz.Format format = attrMap.get(k).getFormat(); if(Clazz.Format.DateTime.equals(format) || Clazz.Format.Date.equals(format)){ String[] dateArray = ObjectMapperHelper.mapper().readValue(v.toString(), String[].class); queryWrapper.ge("attr_json->'$." + k + "'", dateArray[0]); queryWrapper.lt("attr_json->'$." + k + "'", dateArray[1]); }else { queryWrapper.eq("attr_json->'$." + k + "'", v); } }catch (Exception e){ log.error("form data query k:{},v:{} error:{}",k,v,e.getMessage()); } }}
Sqlserver方言实现
import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Service;import java.util.Map;@Slf4j@Service@ConditionalOnDbType(types = {DbType.SQL_SERVER2005,DbType.SQL_SERVER})public class SqlServerFormDataDialectServiceImpl implements FormDataDialectService<FormDataEntity> { @Override public void conditon(QueryWrapper<FormDataEntity> queryWrapper, Map<String, Clazz> attrMap, Object k, Object v) { try { //替换时间类型判断(时间查询为时间段) Clazz.Format format = attrMap.get(k).getFormat(); if(Clazz.Format.DateTime.equals(format) || Clazz.Format.Date.equals(format)){ String[] dateArray = ObjectMapperHelper.mapper().readValue(v.toString(), String[].class); queryWrapper.ge("JSON_VALUE(attr_json, '$." + k + "')", dateArray[0]); queryWrapper.lt("JSON_VALUE(attr_json, '$." + k + "')", dateArray[1]); }else { queryWrapper.eq("JSON_VALUE(attr_json, '$." + k + "')", v); } }catch (Exception e){ log.error("form data query k:{},v:{} error:{}",k,v,e.getMessage()); } }}
最后注意数据库脚本从mysql到sqlserver的转换,可以用微软的工具Microsoft SQL Server Migration Assistant for MySQL,
可参照官网实现。
下载链接:https://www.microsoft.com/en-us/download/details.aspx?id=54257&6B49FDFB-8E5B-4B07-BC31-15695C5A2143=1
来源地址:https://blog.csdn.net/little_pig_lxl/article/details/130485475
--结束END--
本文标题: 系统mysql、sqlserver数据库兼容方案
本文链接: https://lsjlt.com/news/407011.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-10-23
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0