国产化替代实战:SpringBoot项目无缝切换MySQL与OpenGauss(附完整配置代码)

超声探头阵元数量怎么选?128 vs 64阵元DAS算法成像效果对比实验 本文通过对比128阵元与64阵元在DAS算法下的成像效果,深入探讨了超声探头阵元数量的选型策略。实验表明,增加阵元能提升分辨率和对比度,但计算量成倍增长。选型需综合考虑成像区域、阵元间距、系统实时性与成本,在性能与效率间寻求最佳平衡。 阅读详情

国产化替代实战:SpringBoot项目无缝切换MySQL与OpenGauss(附完整配置代码)

最近和几个技术团队交流,发现一个挺普遍的现象:很多原本跑在MySQL上的核心业务系统,因为各种原因,需要开始考虑国产数据库的适配。OpenGauss作为其中的热门选择,经常被提上日程。但现实情况往往不是简单的“一刀切”替换——很多项目需要在一段时间内同时支持MySQL和OpenGauss,实现平滑过渡,或者干脆就设计成长期双数据源并存的架构。

这听起来简单,真做起来却有不少坑。比如,如何让同一套业务代码在两个数据库上都能跑?配置文件怎么管理才不混乱?那些MySQL特有的函数和语法,在OpenGauss里找不到对应怎么办?更别提依赖冲突、事务一致性这些工程细节了。今天,我就结合最近手头一个实际的企业级项目改造经历,把从技术选型到落地配置的完整路径拆解清楚,特别是如何利用dynamic-datasource这个利器,实现真正意义上的“无缝”动态切换。文章会包含大量可直接复用的配置代码和避坑指南,适合正在或即将面临类似挑战的中高级Java开发者。

1. 架构设计与技术选型:为什么是动态数据源?

在决定动手之前,我们先得想清楚目标。所谓“无缝切换”,核心诉求是什么?我总结下来主要是三点:对业务代码侵入性最小、配置管理足够清晰、运行时能够按需动态选择数据源。这意味着,我们理想的状态是,业务层写数据访问逻辑时,基本不用关心底层连的是MySQL还是OpenGauss,这个决策能延迟到运行时甚至请求级别。

基于这个思路,我评估了几种常见方案:

  • 方案A:写两套DAO/Mapper层。这是最直观但也最笨重的办法,所有数据库操作都要写两份,维护成本爆炸,直接否决。
  • 方案B:使用Spring的AbstractRoutingDataSource自研。灵活性最高,但需要自己处理数据源初始化、连接池管理、事务同步等一堆繁琐问题,容易踩坑,项目时间紧的话不推荐。
  • 方案C:采用成熟的动态数据源框架。比如dynamic-datasource-spring-boot-starter,它基于AbstractRoutingDataSource做了大量封装和增强,开箱即用,社区活跃,文档也还算齐全。

显然,方案C是目前综合成本最低、最稳妥的选择。dynamic-datasource不仅支持数据源动态路由,还内置了多种连接池(HikariCP, Druid等)的适配,对MyBatis/MyBatis-Plus的集成也很友好,能极大减少我们的样板代码。

注意:选择dynamic-datasource并不意味着万事大吉。它解决了数据源路由的基础问题,但数据库之间的SQL方言差异、事务管理等更深层的问题,仍然需要我们额外关注和处理。框架是工具,用好工具需要正确的策略。

确定了核心框架,整个技术栈就清晰了:

  • Spring Boot 2.7+ (建议选择长期支持版本)
  • MyBatis-Plus 3.5+ (极大简化单表操作,配合动态数据源效果更佳)
  • dynamic-datasource-spring-boot-starter 3.6+
  • MySQL Connector/J 8.0+
  • OpenGauss JDBC驱动 (基于PostgreSQL JDBC驱动,但建议使用官方适配版本)

2. 工程化配置:从依赖引入到数据源定义

理论说完,我们直接进入实战。首先创建一个全新的Spring Boot工程,或者在你的现有项目中进行改造。

2.1 依赖管理(pom.xml关键片段)

依赖的版本协调是第一步,也是容易出冲突的地方。以下是一个经过验证的、兼容性较好的依赖配置示例:

<properties>
    <java.version>1.8</java.version>
    <spring-boot.version>2.7.18</spring-boot.version>
    <mybatis-plus.version>3.5.5</mybatis-plus.version>
    <dynamic-ds.version>3.6.1</dynamic-ds.version>
</properties>

<dependencies>
    <!-- Spring Boot 基础 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    <!-- 动态数据源核心 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
        <version>${dynamic-ds.version}</version>
    </dependency>

    <!-- MyBatis-Plus (已包含MyBatis) -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>${mybatis-plus.version}</version>
    </dependency>

    <!-- 数据库驱动 -->
    <!-- MySQL -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- OpenGauss (使用官方推荐的驱动) -->
    <dependency>
        <groupId>org.opengauss</groupId>
        <artifactId>opengauss-jdbc</artifactId>
        <version>3.0.0</version>
        <scope>runtime</scope>
    </dependency>

    <!-- 其他工具 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

关键点:确保dynamic-datasource和mybatis-plus-boot-starter的版本兼容。这里选用的是社区反馈比较稳定的组合。OpenGauss驱动使用官方opengauss-jdbc,它兼容PostgreSQL协议,但针对OpenGauss做了优化。

2.2 多环境数据源配置(application.yml)

配置是动态数据源的核心。我们的目标是清晰定义两个数据源(mysql, opengauss),并指定一个默认的(primary)。这里我采用application.yml的多文档块功能,将不同环境的配置分离,保持主配置文件的整洁。

application.yml

spring:
  profiles:
    active: @profiles.active@ # Maven过滤,动态激活环境

---
# 开发环境配置
spring:
  config:
    activate:
      on-profile: dev
  datasource:
    dynamic:
      primary: mysql # 默认使用mysql数据源
      strict: false # 非严格模式,未匹配到数据源时使用默认数据源
      datasource:
        mysql:
          url: jdbc:mysql://localhost:3306/my_app_dev?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
          username: dev_user
          password: dev_pass_123
          driver-class-name: com.mysql.cj.jdbc.Driver
          hikari:
            connection-timeout: 30000
            maximum-pool-size: 20
            minimum-idle: 5
        opengauss:
          url: jdbc:opengauss://192.168.1.100:5432/my_app_dev?currentSchema=public&stringtype=unspecified
          username: og_dev_user
          password: og_dev_pass_123
          driver-class-name: org.opengauss.Driver # 注意驱动类名
          hikari:
            connection-timeout: 30000
            maximum-pool-size: 15 # OpenGauss连接数可适当调整
            minimum-idle: 3
      hikari: # 全局HikariCP配置(可被数据源单独配置覆盖)
        max-lifetime: 1800000
        idle-timeout: 600000

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开发环境开启SQL日志
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      id-type: auto
      logic-delete-field: deleted # 全局逻辑删除字段
      logic-delete-value: 1
      logic-not-delete-value: 0
  mapper-locations:
    - classpath:mapper/**/*.xml
    - classpath:gauss-mapper/**/*.xml # 将OpenGauss专用的Mapper XML分开存放

配置解读:

  1. primary: mysql:设置默认数据源。在代码中未显式指定数据源时,所有操作都会落在MySQL上。
  2. 分别为mysql和opengauss定义了完整的连接信息。特别注意OpenGauss的driver-class-name和url格式。currentSchema参数可以指定默认的模式(类似MySQL的数据库)。
  3. mapper-locations配置了两个路径。这是实现SQL方言隔离的关键。我们可以把兼容性好的、或通用的SQL放在mapper目录下,而将包含OpenGauss特有函数或语法的SQL放在gauss-mapper目录下。框架会根据当前使用的数据源,自动寻找对应目录下的XML文件(需要配合后续的注解使用)。

2.3 数据源切换注解与上下文持有器

配置好数据源后,我们需要一种方式来告诉程序:“现在这个方法要用opengauss数据源”。dynamic-datasource提供了@DS注解。

1. 创建线程上下文持有器 虽然@DS注解可以直接用在Service或Mapper上,但在复杂业务流中,我们可能需要在运行时动态决定数据源。这时,一个基于ThreadLocal的上下文工具类就非常有用。

/**
 * 动态数据源上下文持有器
 */
public class DynamicDataSourceContextHolder {
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();

    /**
     * 设置当前线程的数据源标识
     */
    public static void setDataSourceKey(String key) {
        CONTEXT_HOLDER.set(key);
    }

    /**
     * 获取当前线程的数据源标识
     */
    public static String getDataSourceKey() {
        return CONTEXT_HOLDER.get();
    }

    /**
     * 清除当前线程的数据源标识
     */
    public static void clearDataSourceKey() {
        CONTEXT_HOLDER.remove();
    }
}

2. 自定义切面实现动态路由 我们可以创建一个AOP切面,在进入Service方法前,根据自定义规则(比如请求头、参数内容)来动态设置数据源。

@Aspect
@Component
@Slf4j
public class DynamicDataSourceAspect {

    @Before("@annotation(com.yourpackage.annotation.TargetDataSource)")
    public void beforeSwitchDataSource(JoinPoint joinPoint) {
        // 这里可以编写复杂的路由逻辑
        // 例如:从请求头获取"X-Data-Source: opengauss"
        // 或者根据方法参数中的某个字段判断
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String dsKey = request.getHeader("X-Data-Source");
        
        if (StringUtils.hasText(dsKey) && ("mysql".equalsIgnoreCase(dsKey) || "opengauss".equalsIgnoreCase(dsKey))) {
            DynamicDataSourceContextHolder.setDataSourceKey(dsKey.toLowerCase());
            log.debug("动态切换数据源至: {}", dsKey);
        }
        // 如果没有指定,则使用@DS注解或默认数据源
    }

    @After("@annotation(com.yourpackage.annotation.TargetDataSource)")
    public void afterClearDataSource(JoinPoint joinPoint) {
        DynamicDataSourceContextHolder.clearDataSourceKey();
        log.debug("清理动态数据源上下文");
    }
}

这样,我们就拥有了注解驱动和编程式驱动两种切换数据源的能力,灵活性大大增加。

3. 解决兼容性难题:SQL方言与函数映射

这是国产化替代中最硬核、最耗时的部分。MySQL和OpenGauss(源自PostgreSQL)的SQL语法和内置函数存在不少差异。直接迁移SQL脚本大概率会失败。

3.1 常见不兼容点及解决方案

下表列举了一些高频出现的差异点及其处理方式:

MySQL 函数/语法OpenGauss / PostgreSQL 对应方案说明与注意事项
IFNULL(expr1, expr2)COALESCE(expr1, expr2)COALESCE是SQL标准函数,两者功能完全一致,优先推荐使用COALESCE,因为它兼容性更好。
DATE_FORMAT(date, format)TO_CHAR(date, format)日期格式字符串不同。MySQL的%Y-%m-%d在PG/OpenGauss中是YYYY-MM-DD。需要重写格式字符串。
STR_TO_DATE(str, format)TO_DATE(str, format)同样需要注意格式字符串的差异。
GROUP_CONCAT(...)STRING_AGG(...)函数名和参数顺序可能不同。STRING_AGG(expr, delimiter)。
LIMIT offset, row_countLIMIT row_count OFFSET offset分页语法是必须修改的。MyBatis-Plus的分页插件可以自动处理,但手写XML需要留意。
ON DUPLICATE KEY UPDATEON CONFLICT (...) DO UPDATE SET“插入冲突更新”语法完全不同。需要重写相关插入语句。
自增主键序列(Sequence)MySQL的AUTO_INCREMENT对应OpenGauss的SERIAL类型或手动创建序列+默认值。实体类配置@TableId(type = IdType.AUTO)在OpenGauss下可能需要调整为IdType.INPUT并配合序列。

3.2 实践策略:Mapper XML的隔离与适配

面对这些差异,我推荐“隔离+适配”的策略,而不是试图写一套完全兼容两者的SQL。

1. 目录隔离 如前所述,在mybatis-plus.mapper-locations中配置两个路径。通用SQL放classpath:mapper/,OpenGauss专用SQL放classpath:gauss-mapper/。

2. 使用@DS注解指定Mapper的数据源 在Mapper接口上使用@DS注解,将其绑定到特定数据源。这样,当调用该Mapper的方法时,框架不仅会路由到正确的数据库,还会自动从对应的目录加载XML文件。

// UserMapper.java
@DS("mysql") // 这个Mapper默认使用mysql数据源,会去mapper/目录找XML
public interface UserMapper extends BaseMapper<User> {
    User selectComplexUser(@Param("userId") Long userId);
}

// GaussUserMapper.java
@DS("opengauss") // 这个Mapper专用于opengauss,会去gauss-mapper/目录找XML
public interface GaussUserMapper extends BaseMapper<User> {
    User selectComplexUser(@Param("userId") Long userId);
}

3. Service层聚合 在Service层,我们可以根据需求注入不同的Mapper,或者利用前面提到的动态切面来统一接口。

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper; // 对应MySQL
    @Autowired
    private GaussUserMapper gaussUserMapper; // 对应OpenGauss

    @Override
    @DS("mysql") // 此方法固定使用MySQL
    public User getUserFromMySQL(Long id) {
        return userMapper.selectById(id);
    }

    @Override
    @DS("opengauss") // 此方法固定使用OpenGauss
    public User getUserFromOpenGauss(Long id) {
        return gaussUserMapper.selectById(id);
    }

    @Override
    @TargetDataSource // 使用自定义切面,根据运行时条件动态决定数据源
    public User getUserDynamic(Long id, String source) {
        // 方法内部可以不关心数据源,由切面根据`source`参数或请求头处理
        // 假设这里有一个通用的Mapper,其XML有两套版本
        return commonMapper.selectById(id);
    }
}

4. XML示例对比 假设有一个复杂的查询,涉及日期格式化。

mapper/UserMapper.xml (MySQL版本):

<select id="selectUsersByDate" resultType="UserVO">
    SELECT 
        id, 
        name,
        DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:%s') AS createTimeStr
    FROM user
    WHERE create_time >= STR_TO_DATE(#{startDate}, '%Y-%m-%d')
</select>

gauss-mapper/GaussUserMapper.xml (OpenGauss版本):

<select id="selectUsersByDate" resultType="UserVO">
    SELECT 
        id, 
        name,
        TO_CHAR(create_time, 'YYYY-MM-DD HH24:MI:SS') AS createTimeStr
    FROM "user" -- OpenGauss对表名大小写敏感,通常小写或加引号
    WHERE create_time >= TO_DATE(#{startDate}, 'YYYY-MM-DD')
</select>

4. 高级主题:事务管理与性能调优

当引入多数据源后,事务管理会变得复杂。Spring的@Transactional默认只能管理一个数据源的事务。

4.1 多数据源事务处理

对于需要跨数据源保证一致性的操作(本例中较少,但需知晓),需要考虑分布式事务方案,如Seata。但对于大多数“读MySQL,写OpenGauss”或完全分离的业务场景,我们可以这样做:

  1. 避免跨库事务:从业务设计上,确保一个业务单元内的所有数据库操作都针对同一个数据源。
  2. 使用@DSTransactional注解:dynamic-datasource框架提供了@DSTransactional注解,它可以在切换数据源的同时,管理该数据源上的事务。但它不支持跨数据源的全局事务。
    @Service
    public class OrderService {
        @DS("opengauss")
        @DSTransactional // 在opengauss数据源上开启事务
        public void createOrder(Order order) {
            // ... 操作opengauss数据库
        }
    }
    
  3. 最终一致性:对于强一致性要求不高的场景,可以通过消息队列、补偿机制(如重试、对账)来实现最终一致性。

4.2 连接池与性能监控

不同的数据库,其连接池的最佳配置可能不同。我们在配置部分已经为每个数据源单独配置了HikariCP的参数。除此之外,监控至关重要。

  • 启用Druid监控(如果使用Druid):Druid连接池提供了强大的监控统计功能。如果选择Druid,可以配置stat、wall等过滤器,并通过Web界面查看SQL执行情况、连接池状态。
  • 使用Spring Boot Actuator:暴露/actuator/metrics/hikaricp.connections.*等端点,可以集成到Prometheus+Grafana中做可视化监控。
  • 慢SQL日志:在MySQL和OpenGauss数据库服务器端分别开启慢查询日志,定期分析,优化索引和SQL语句。

4.3 数据同步与双写策略

在过渡期,你可能需要保持两个数据库的数据基本同步。可以考虑以下策略:

  1. 应用层双写:在Service层的重要写操作中,同时写入两个数据库。这种方式逻辑简单,但需要处理好失败补偿和性能开销。务必保证操作是幂等的。
    @Transactional(rollbackFor = Exception.class) // 注意事务边界
    public void createUser(User user) {
        // 先写主库(如MySQL)
        userMapper.insert(user);
        // 再写OpenGauss,如果失败,可以记录日志或放入重试队列,不影响主流程
        try {
            gaussUserMapper.insert(user);
        } catch (Exception e) {
            log.error("同步用户数据到OpenGauss失败: {}", user.getId(), e);
            // 发送到消息队列,进行异步重试
            retryMessageSender.send(user);
        }
    }
    
  2. 基于Binlog/Canal的异步同步:使用Canal监听MySQL的binlog,实时将数据变更同步到OpenGauss。这种方式对应用层无侵入,延迟低,是更优雅的解决方案,但架构复杂度更高。

整个改造过程,就像是在给行驶中的汽车换轮子,需要缜密的计划和细致的操作。从我的经验来看,前期花足够的时间进行差异分析、制定清晰的Mapper隔离策略,远比在凌乱的代码中事后修补要高效得多。配置代码固然重要,但背后的设计思路和应对差异化的策略,才是项目能否平稳落地的关键。

EJB学习笔记——会话Bean 1.EJB3简介:EJB是企业级java bean(Enterprise Java Bean)开发技术,是基于IIOP协议的分布式远程方法调用技术(RMI),EJB3在JavaEE5中被正式引入,去掉了EJB2以前的复制度,使得EJB3更加轻量级,同时将实体Bean单独分拆成为JPA规范,从而使EJB3更加专注于会话Bean和消息驱动Bean的业务逻辑,同时EJB3中全面支持java注解方式,大大简化开发的难度提高开发效率。2.在客户端调用一个简单EJB3程序:首先使用一个简单例子演示客户端调用EJB3的基 阅读详情

相关推荐

深入理解EJB:状态会话Bean与无状态会话Bean

企业级Java Bean(EJB)是Java EE(现在称为Jakarta EE)平台的核心组件模型。它提供了一种框架,允许开发者编写可扩展、事务性和安全的服务器端业务逻辑。EJB技术的出现简化了复杂应用的开发,通过抽象各种企业级服务(如事务管理、安全认证等)来减轻开发者的负担。无状态会话Bean(Stateless Session Bean)是企业级Java Bean(EJB)的一部分,属于会话Bean的一种,它不保存客户端的状态信息。

weixin_42405592的博客 505

【EJB】会话Bean(Session Bean)

会话bean封装了可以由客户端通过本地,远程或Web服务客户端视图以编程方式调用的业务逻辑。要访问部署在服务器上的应用程序,客户机将调用会话Bean的方法。会话bean为客户端执行工作,通过在服务器内执行业务任务来避免复杂性。

张姐姐聊编程 863

关于有状态和无状态会话bean的解释

NULL 博文链接:https://caizhongda.iteye.com/blog/341007

会话bean

在本文中,将讨论EJB会话Beans的知识——EJB客户端应用程序所用到的核心业务服务对象,有助于理解简单新颖的EJB会话Bean模型。     什么是会话bean?     会话Bean是Java组件,其既可运行于独立的EJB容器中,也可运行于作为标准Java平台、Java EE应用程序服务器一部分EJB容器中。这些Java组件通常用于建模某一特定用户任务,如输入顾客信息或实现某一维持客户端

劝学 2168

产业园区如何高效对接企业技术需求与高校科研成果?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

2024年上半年网络工程师下午真题及答案解析

位于MPLS域边缘、连接其他网络的LSR称为( 3 ),区域内部的LSR称为核心LSR(CoreLSR)IP报文进入MPLS网络时,MPLS入口设备分析IP报文的内容并为其添加合适的标签,所有MPLS网络中的LSR根据标签转发数据,当该IP报文离开MPLS网络时,标签由出口LER弹出。LSP的出口LER称为( 6 )。某高校网络拓扑如下图所示,两校区核心(CORE-1、CORE-2),出口防火墙(NGFW-1、NGFW-2)通过校区间光缆互联,配置OSPF实现全校路由收敛,两校区相距40km。

bsefef的博客 2474

EJB——会话bean(一)

会话bean的目的是建模业务处理或者操作,特别是系统用户能察觉到的。会话bean是EJB中最容易但也最通用的部分。 会话bean有两种类型:无状态类型和有状态类型。 无状态bean package com.ejb3inaction.actionbazaar.buslogic; import javax.ejb.Stateless;import javax.persistenc

徐凤竹 程序人生 898

Facebook登录协议逆向实战:从加密参数到完整流程解析(附Python代码)

本文深入解析了Facebook登录协议的逆向工程实战,详细拆解了从关键加密参数(如`lgndim`、`encpass`)定位到完整登录流程的实现。文章提供了Python代码示例,重点阐述了加密逻辑的深度解析、加密函数的本地化实现,并解决了Crypto.js异步调用等常见问题,为研究Web安全和协议逆向的开发者提供了实用参考。

metal的博客 1311

Java之旅EJB(2)——三种bean之会话bean

前面我们大致讲过ejb是什么,这里不再对定义进行讲解,主要是讲解内部的组成。  1.      Bean分类   会话bean(session bean)   负责与客户端交互,是编写业务逻辑的地方,在会话bean中可以通过jdbc直接操作数据库,但大多数情况下都是通过实体bean来完成对数据库的操作。   实体bean(Entity bean)   它实际上属于java持久化规范(简称

李晓娜 2558

避坑指南:CoppeliaSim逆运动学仿真常见报错解决方案(附UR5+RG2爪完整Lua脚本)

本文针对CoppeliaSim机器人仿真中常见的逆运动学报错问题,提供了详细的避坑指南和解决方案。文章以UR5机械臂与RG2夹爪组合为例,深入剖析了模型装配、Dummy节点配置、Lua脚本编写等关键步骤中的常见错误,并附带了完整的、带错误处理的脚本代码,帮助用户快速定位并解决IK仿真失败问题,提升仿真效率。

weixin_29054399的博客 267

DAGGER vs 传统模仿学习:为什么数据聚合能提升模型性能?

本文深入对比了DAGGER与传统模仿学习,揭示了传统方法因“分布不匹配”导致性能下降的根源。DAGGER通过动态的**数据聚合**机制,在智能体自身策略产生的状态分布上收集专家数据,从根本上解决了误差累积问题,从而显著提升了模型在实际部署中的鲁棒性和性能。

weixin_29170327的博客 234

Session Bean(会话Bean)

Session Bean的种类:分为有状态的会话Bean和无状态的会话Bean(Stateful Session Bean和Stateless Session Bean) Session Bean的作用:Session Bean是用来实现业务逻辑的,Session Bean可以直接操作数据库,通过Entity Bean实现数据库的访问 无状态的Bean:无状态Bean能够被启用很多次,该B...

weixin_30364325的博客 477

【3D无序抓取】--终极技术详解

3D无序抓取技术详解:从感知到执行的全流程技术方案 本文系统梳理了3D无序抓取(Bin Picking)的核心技术栈,涵盖3D感知、抓取规划和机器人执行三大环节。在3D感知层,详细介绍了点云采集与预处理方法(PCL/Open3D)、物体分割(PointNet++)和位姿估计(PVN3D/DenseFusion)等关键技术。抓取规划部分重点解析了抓取生成(GraspNet)、质量评估(Dex-Net)和动态避障(MoveIt!)算法。机器人执行环节则涉及路径规划、力控技术和末端执行器选型。同时提供了完整的工具

weixin_45590420的博客 597

国产化改造实战:SpringBoot项目无缝切换MySQL与OpenGauss(附完整配置)

本文详细介绍了SpringBoot项目在国产化改造中如何实现MySQL与OpenGauss数据库的无缝切换,涵盖动态数据源配置、MyBatis多方言支持及事务管理等关键技术。通过实战案例和完整配置指南,帮助开发者高效完成数据库迁移,确保业务连续性和系统稳定性。

data3的博客 759

CentOS-7-x86_64经典版本的含义

这个版本的ISO文件包含了所有的软件包,所以文件比较大,但在安装过程中不需要下载软件包。如果你有一个稳定的网络连接,并且希望安装时能够选择最新的软件包,或者只安装特定的软件包,那么可以选择NetInstall版本。在这里,它可能是指这个ISO文件发布于2207年2月,但是这似乎是一个错误,因为截止到现在(2022年)的时间,都没有到达2207年。另外,还有一个DVD版本,这个版本的ISO文件包含了大部分常用的软件包,安装时可能需要网络连接,但比NetInstall版本少一些。

舒一笑的博客 3535

AMS TMF8820/21/28 SPAD 掩码和模式选择

为了实现最快的测距周期,将报告周期设置在测距周期以下的毫秒,以确保不会有等待时间。除了8X8固定了pixel的位置意外,其他模式客户可以设计自己的spad掩码,并将spad单独分配给通道。对于这些spad掩码,有一些约束。左下角提示红色代表光学中心,绿色方框表示单个spad,每个MP里可能有2X3个spad,也有2X5个spad,也有3X6+3个spad,这部分适配光学,最大的程度的利用spad区域。以下是几种预定义的spad掩码,非常灵活的配置,来适配各种3X3,4X4,8X8的模式选择。

dream it possible 700

会话 Bean(Session Bean)

Session Bean 是实现业务逻辑的地方。简单地说,像我们要实现两数相加或是从数据库中读取数据,都是通过Session Bean 来实现。根据是否可以维护会话状态,Session Bean 分为有状态 bean 和无状态 bean。有状态 bean 可以维护会话状态,无状态 bean 不维护会话状态。要维护会话状态,意味着 EJB 容器要为每个用户创建一个 bean实例,并通过该实例保存着与...

iteye_8614的博客 423

【FreeSwitch开发实践】外呼网关配置(拨打电话)

FreeSwitch开发一个重要应用是外呼,所谓外呼就拨打真实电话或手机号呼叫,配合语音机器人可以实现智能客服的功能。外呼配置主要是配置外呼服务器,外呼服务器主要指SIP网关,每个外呼服务器就是一个SIP节点,FreeSwitch服务也可以是一个SIP节点。本文主要介绍了FreeSwitch外呼相关配置,主要有外呼配置的模式,包括注册模式和非注册模式网关加载的查看方法拨号中常见的呼出配置和呼入配置如果觉得有些帮助或觉得文章还不错,请关注一下博主,你的关注是我持续写作的动力。............

xiao2macf的专栏 1万+

EJB中的三种bean初步介绍及会话bean

EJB中的三种bean1.会话bean(session bean) 负责与客户端交互,是编写业务逻辑的地方,在会话bean中可以通过jdbc直接操作数据库,但大多数情况下都是通过实体bean来完成对数据库的操作. 2.实体bean(entity bean) 它实际上属于java持久化规范(简称JPA)里的技术, JPA的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hi...

weixin_30279751的博客 158

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Spring Boot 3.0+MySQL+Redis项目的国产化替代方案

‌:华为主导的开源Linux发行版,支持ARM/x86架构,通过LTS版本提供长期维护,适合服务器环境部署。‌:完全兼容Redis 5.0协议,采用RocksDB引擎实现持久化,单实例支持TB级数据‌。‌:支持冷热分层存储,性能较Redis提升2.8倍,需评估云服务成本‌。‌:强一致性架构,适合金融核心系统,迁移需测试事务隔离级别兼容性‌。‌:Java实现,代码自主率95%,适用于党政军等高安全场景‌。‌:提供数据迁移工具(如DTS),支持在线迁移与断点续传‌。‌:支持WAR包部署或内嵌模式,需配置。

1636

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

spring全家桶平替 信创国产化 solon 初体验

随着信创项目的发展,国产化的步伐越来越稳了,作为Java后端开发必学必会的框架spring生态,已经形成了后端技术栈代表,信创项目讲究自主可控,国产开源solon应运而生,值得大家一学。

yueeryuanyi的博客 2098

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

有状态会话Bean和无状态会话Bean的区别

    Session   Bean   主要的目的是让程序开发者将逻辑层抽离;    Entity   Bean   主要是资料组件,  Entity   Bean   主要的目的,在于提供资料,也就是说程序设计师可以将   Entity   Bean   当程序资料;     Message   Driven   Bean   与   Session   Bean   或是   Entity 

lingxiao301415的专栏 1万+

有状态会话bean

在会话bean综述中,描述了无状态和有状态bean的区别在于客户端和服务器之间交互形式不同。对于无状态会话bean,交互的开始和结束都在同一个方法中。有时客户端需要发出多个服务请求(需要调用多个方法),而每个请求需要访问或者考虑前面的请求结果。有状态会话bean的出现就是为了处理这种情况,通过向客户端提供一个专用的服务(某一个可以保留前面状态的bean),当客户端获得bean的引用时启动该服务,并

郗晓勇|利己者生,利人者恒 3720

无状态会话Bean与有状态会话Bean的区别以及实例池

李绪成的一亩三分地 2694

调用本地会话Bean和远程会话BEAN/EJB的简单例子(环境:JBOSS7.1 JDK7)

一个小的调用本地EJB的作业,不难,接口什么的非常好写,但是由于网上的jndi千奇百怪,而且这个东西太老了,我上课也没听,导致只能搞个远程的,本地的概念什么的都不是很清楚,所以弄了很久。(环境:JDK7+eclipse+JBOSS7.1) 一会有空总结一下,主要参考老师的PPT(慕课网站http://mooc1.chaoxing.com/course/203574850.html)和这两篇博客...

qq_38941327的博客 791
上一篇: 从原理到代码:手把手教你理解DeepSeek-V3.2的闪电索引器设计
下一篇: Spring Boot导出Excel踩坑实录:为什么我的接口返回值会导致Stream is closed?
python9snake
博客等级 码龄1天 0粉丝 1724原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值