SpringBoot整合达梦数据库

简介: SpringBoot整合达梦数据库

安装配置

软件安装

下载地址:https://www.dameng.com/view_61.html

本文以x86 win64 DM8为例

安装完毕后打开DM数据库配置助手创建数据库,设置字符集utf8,去除字符大小写敏感

创建表空间及用户,最好是一个库对应一个用户一个表空间,创建用户时需要指定对应表空间

需要对用户分配DBA操作权限

数据表迁移

针对现有项目或框架库需要同步迁移到达梦数据库,本文以mysql5.7为例,打开DM数据迁移工具,注意保持对象名大小写,选择表时全部取出再全选,迁移的表名和字段名就与原数据库保持一致

maven引用

        <dependency>
            <groupId>com.dameng</groupId>
            <artifactId>DmJdbcDriver18</artifactId>
            <version>8.1.1.193</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.0</version>
        </dependency>
AI 代码解读

数据库配置

使用druid管理连接池,去除wall的配置否则会报错

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
      driverClassName: dm.jdbc.driver.DmDriver
      url: jdbc:dm://localhost:5236/ROOT?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
      username: ROOT
      password: abcd@1234
    filters: stat,slf4j
AI 代码解读

兼容代码

映射成LinkHashMap

数据会在达梦的数据库驱动中强制大写,这对某些接口的数据返回给前端数据大小写出现问题,影响范围较大

JdbcTemplate处理

我们可以通过混合使用jdbcTemplate进行查询的通用操作,调用query方法,传入自定义的ResultSetExtractor,得到jdbc原生的ResultSet对象,取出ResultSetMetaData转换成DmdbResultSetMetaData,其中的columns对象为私有对象且无方法访问,通过反射取出即可,通过columns获取到数据库实际的列名

    public List<LinkedHashMap<String, Object>> findListByParam(String sqlText, Map<String, Object> map) {
   
   
        List<LinkedHashMap<String, Object>> result = new ArrayList<>();
        List<Object> paramList = new ArrayList<>();
        //解析sqlText中的占位符#{xxxx}
        String regex = "\\#\\{(?<RegxName>[\\w.]*)\\}";
        String sqlTextCopy = sqlText;
        Pattern pattern = Pattern.compile(regex);

        Matcher matcher = pattern.matcher(sqlTextCopy);
        while (matcher.find()) {
   
   
            String paramNameSymbol = matcher.group(0);
            sqlText = sqlText.replace(paramNameSymbol, " ? ");
        }
        logger.debug("【sqlText】:" + sqlText);

        //参数赋值
        matcher = pattern.matcher(sqlTextCopy);
        while (matcher.find()) {
   
   
            String paramNameSymbol = matcher.group(0);
            String paramName = paramNameSymbol.replace("#", "").replace("{", "").replace("}", "");
            Object paramValue = map.get(paramName);
            logger.debug("【paramName】:" + paramName);
            logger.debug("【paramValue】:" + paramValue);
            paramList.add(paramValue);
        }

        jdbcTemplate.query(sqlText, paramList.toArray(), new ResultSetExtractor<Object>() {
   
   
            @Override
            public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
   
   
                try {
   
   
                    ResultSetMetaData rsMetaData = rs.getMetaData();
                    Column[] dm_columns = null;
                    if (dataBaseInfoUtil.getUsingDataBaseType() == GlobalEnum.DataBaseType.DM) {
   
   
                        ResultSetMetaDataProxyImpl resultSetMetaDataProxy = (ResultSetMetaDataProxyImpl) rsMetaData;
                        DmdbResultSetMetaData dmdbResultSetMetaData = (DmdbResultSetMetaData) resultSetMetaDataProxy.getRawObject();
                        Class dataClass = DmdbResultSetMetaData.class;
                        Field field = dataClass.getDeclaredField("columns");
                        field.setAccessible(true);
                        dm_columns = (Column[]) field.get(dmdbResultSetMetaData);
                    }
                    while (rs.next()) {
   
   
                        LinkedHashMap<String, Object> resultitem = new LinkedHashMap<>();
                        for (int i = 1; i <= rsMetaData.getColumnCount(); i++) {
   
   
                            String columnName = "";
                            if (dataBaseInfoUtil.getUsingDataBaseType() == GlobalEnum.DataBaseType.DM) {
   
   
                                columnName = dm_columns[i - 1].name;
                            } else {
   
   
                                columnName = rsMetaData.getColumnName(i);
                                ;
                            }
                            Object columnValue = rs.getObject(columnName);
                            resultitem.put(columnName, columnValue);
                        }
                        result.add(resultitem);
                    }

                } catch (Exception e) {
   
   
                    e.printStackTrace();
                } finally {
   
   
                    return null;
                }
            }
        });
        return result;
    }
AI 代码解读

与mybaits统一数据源

在使用事务时,因为查询操作通过jdbcTemplate,更新操作通过myabtis,在某些隔离级别下会查询不到未提交的数据,所以需要统一数据源都为druid管理的datasource,这里的dynamicDataSource为我自定义的数据源处理对象,继承自spring的AbstractRoutingDataSource,为了处理多数据源情况

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
   
   
        //SpringBootExecutableJarVFS.addImplClass(SpringBootVFS.class);
        final PackagesSqlSessionFactoryBean sessionFactory = new PackagesSqlSessionFactoryBean();
        sessionFactory.setDataSource(dynamicDataSource());
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:mybatis/**/*Mapper.xml"));
        //关闭驼峰转换,防止带下划线的字段无法映射
        sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(false);
        return sessionFactory.getObject();
    }

    @Bean
    public JdbcTemplate jdbcTemplate(){
   
   
        JdbcTemplate jdbcTemplate = null;
        try{
   
   
            jdbcTemplate = new JdbcTemplate(dynamicDataSource());
        }catch (Exception e){
   
   
            e.printStackTrace();
        }
        return jdbcTemplate;
    }
AI 代码解读

映射成实体类

统一将查询操作结果转换成LinkHashMap键值对,再通过BeanMap映射成对应的实体类

clob长文本处理

                    Object value = map.get(resultkey);
                    if(value instanceof ClobProxyImpl){
   
   
                        try {
   
   
                            value =  ((ClobProxyImpl) value).getSubString(1,(int)((ClobProxyImpl) value).length());
                        } catch (Exception e) {
   
   
                            e.printStackTrace();
                        }
                    }
AI 代码解读

blob二进制处理

                    Object value = map.get(resultkey);
                    if(value instanceof DmdbBlob){
   
   
                        try {
   
   
                            DmdbBlob dmdbBlob = (DmdbBlob)value;
                            value = FileUtil.convertStreamToByte(dmdbBlob.getBinaryStream());
                        } catch (Exception e) {
   
   
                            e.printStackTrace();
                        }
                    }
AI 代码解读
相关文章
【赵渝强老师】达梦数据库的线程结构
达梦数据库采用单进程、多线程结构,利用对称服务器架构实现高效资源利用与可扩展性。其核心线程类型包括监听线程(管理客户端连接)、I/O线程(处理数据页读写)、工作线程(执行数据操作)、调度线程(定时任务管理)和日志刷新线程(确保REDO日志刷盘)。通过合理分工与同步机制,达梦数据库实现了高性能与稳定性。视频讲解进一步详细介绍了各线程的功能与协作方式。
【赵渝强老师】达梦数据库的线程结构
【赵渝强老师】在Docker中运行达梦数据库
本文介绍了在Docker容器中部署达梦数据库(DM 8)的具体步骤,包括创建文件夹、下载安装包、导入镜像、启动容器、登录数据库及查看状态等操作。同时,通过视频讲解辅助理解。文中还分析了将数据库服务容器化的潜在问题,如数据安全性、硬件资源争用、网络带宽占用和额外隔离带来的挑战,指出数据库服务在生产环境中可能不适合容器化的原因。
191 4
【赵渝强老师】在Docker中运行达梦数据库
【赵渝强老师】达梦数据库的目录结构
本文介绍了达梦数据库(DM 8)安装成功后的目录结构查看方法,通过Linux的`tree`命令展示各目录功能,如`bin`存放可执行文件、`data`为数据库实例目录等。还提供了视频讲解及`data`目录下具体文件示例,帮助用户深入了解数据库文件组成与作用。
135 23
【赵渝强老师】达梦数据库的逻辑存储结构
本文介绍了达梦数据库的存储结构,包括逻辑和物理存储两部分。逻辑存储结构由数据库(Database)、表空间(Tablespaces)、段(Segments)、簇(Cluster)和页(Page)组成。数据库是最大逻辑单元,包含所有表、索引等;表空间由数据文件组成,用于存储对象;段由簇构成,簇包含连续的数据页;页是最小存储单元。文中还提供了查询表空间、段和页大小的SQL语句,并附有视频讲解和示意图。
140 7
【赵渝强老师】达梦数据库的数据库对象
达梦数据库包含基本与复杂两大类数据库对象。基本对象如表、索引、视图、序列和同义词,通过单一DDL语句创建和管理。表是数据存储核心,支持多种数据类型;索引提升查询速度,常见类型包括聚集、唯一、函数等索引;视图提供虚表功能;序列生成有序整数;同义词简化对象访问。复杂对象包括存储过程、函数和触发器,需用DMSQL语言开发,适用于更复杂的业务逻辑处理。文中通过实例详细介绍了各类对象的创建与使用方法。
142 3
【赵渝强老师】达梦数据库的客户端工具
本文介绍了达梦数据库的多种工具及其使用方法,包括disql交互式查询工具、数据库配置助手DBCA、DM管理工具、DM服务查看器、DM控制台工具、DM数据迁移工具、DM性能监视工具以及DM审计分析工具。每种工具的功能和操作步骤均有详细说明,并配有相关图片和代码示例,帮助用户更好地理解和使用这些工具,提升数据库管理和维护效率。
307 1
【赵渝强老师】达梦数据库的归档模式
本文介绍了达梦数据库备份与恢复中重做日志文件的作用,重点讲解了归档模式的必要性及其配置方法。文章分析了非归档模式可能导致的数据丢失问题,并推荐使用归档模式以保障数据一致性和完整性。归档模式分为本地归档和远程归档:本地归档将重做日志存储在本地,而远程归档适用于集群环境,确保所有节点拥有完整日志。文中还详细展示了如何通过SQL命令开启归档模式,包括切换状态、设置路径及验证配置等步骤,并附有视频教程辅助理解。
112 1
【赵渝强老师】达梦数据库的内存结构
本文介绍了达梦数据库管理系统的内存结构,包括内存池、缓冲区、排序区和哈希区。内存池分为共享内存池和运行时内存池,能够提高内存申请与释放效率,并便于监控内存使用情况。缓冲区涵盖数据缓冲区、日志缓冲区、字典缓冲区和SQL缓冲区,用于优化数据读写和查询性能。排序区和哈希区分别提供排序和哈希连接所需的内存空间,通过合理配置参数可提升系统效率。文内附有具体配置示例及视频讲解,帮助用户深入理解达梦数据库的内存管理机制。
【赵渝强老师】达梦数据库的物理存储结构
本文介绍了达梦数据库的存储结构及各类物理文件的作用。达梦数据库通过逻辑和物理存储结构管理数据,包含配置文件(如dm.ini、sqllog.ini)、控制文件(dm.ctl)、数据文件(*.dbf)、重做日志文件(*.log)、归档日志文件、备份文件(*.bak)等。配置文件用于功能设置,控制文件记录数据库初始信息,数据文件存储实际数据,重做日志用于故障恢复,归档日志增强数据安全性,备份文件保障数据完整性,跟踪与事件日志辅助问题分析。这些文件共同确保数据库高效、稳定运行。
117 0
【赵渝强老师】达梦数据库MPP集群的架构
达梦数据库提供大规模并行处理(MPP)架构,以低成本实现高性能并行计算,满足海量数据存储和复杂查询需求。DM MPP采用完全对等无共享体系,消除主节点瓶颈,通过多节点并行执行提升性能。其执行流程包括主EP生成计划、分发任务、各EP并行处理及结果汇总返回。为确保高可用性,建议结合数据守护部署。
107 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问