You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot中AttributeConverter自动装配Bean失败问题求助

问题根源

你手动配置双数据库的EntityManager时,Hibernate会自行实例化AttributeConverter实现类,这些实例不受Spring容器管理,因此Spring的依赖注入机制无法对其生效,导致EncryptionUtil始终为null。

解决方案

方案1:让Hibernate使用Spring管理的Converter实例

在手动配置LocalContainerEntityManagerFactoryBean时,将Spring容器中的EncryptionConverter实例注册到Hibernate的配置中,确保Hibernate使用Spring托管的转换器实例。

示例代码:

@Bean
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(EntityManagerFactoryBuilder builder, 
                                                                         DataSource primaryDataSource,
                                                                         EncryptionConverter encryptionConverter) {
    Map<String, Object> hibernateProps = new HashMap<>();
    // 添加上你原有的Hibernate配置(如dialect、show_sql等)
    // 注册Spring管理的Converter
    hibernateProps.put("hibernate.converters", Collections.singletonList(encryptionConverter));
    
    return builder
            .dataSource(primaryDataSource)
            .packages("com.yourproject.entity.primary") // 主库实体包
            .persistenceUnit("primaryPU")
            .properties(hibernateProps)
            .build();
}

// 从库的EntityManagerFactory配置同理,需注入EncryptionConverter并添加到hibernateProps中
@Bean
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(EntityManagerFactoryBuilder builder, 
                                                                           DataSource secondaryDataSource,
                                                                           EncryptionConverter encryptionConverter) {
    Map<String, Object> hibernateProps = new HashMap<>();
    // 从库Hibernate配置
    hibernateProps.put("hibernate.converters", Collections.singletonList(encryptionConverter));
    
    return builder
            .dataSource(secondaryDataSource)
            .packages("com.yourproject.entity.secondary") // 从库实体包
            .persistenceUnit("secondaryPU")
            .properties(hibernateProps)
            .build();
}

同时,EncryptionConverter需要同时保留@Converter和@Component注解,并用构造器注入EncryptionUtil(构造器注入比字段注入更可靠,避免代理问题):

@Component
@Converter(autoApply = true)
public class EncryptionConverter implements AttributeConverter<String, String> {

    private final EncryptionUtil encryptionUtil;

    public EncryptionConverter(EncryptionUtil encryptionUtil) {
        this.encryptionUtil = encryptionUtil;
    }

    @Override
    public String convertToDatabaseColumn(String attribute) {
        return encryptionUtil.encrypt(attribute);
    }

    @Override
    public String convertToEntityAttribute(String dbData) {
        return encryptionUtil.decrypt(dbData);
    }
}

方案2:静态持有Spring上下文获取工具类(应急方案)

如果不方便修改EntityManager配置,可以调整EncryptionUtil,让它通过静态方式暴露实例:

@Component
public class EncryptionUtil implements ApplicationContextAware {
    private static EncryptionUtil instance;

    // 你的AES256加解密方法
    public String encrypt(String data) {
        // 实现逻辑
    }

    public String decrypt(String data) {
        // 实现逻辑
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        instance = applicationContext.getBean(EncryptionUtil.class);
    }

    public static EncryptionUtil getInstance() {
        return instance;
    }
}

然后在EncryptionConverter中直接调用静态方法获取实例:

@Converter(autoApply = true)
public class EncryptionConverter implements AttributeConverter<String, String> {

    @Override
    public String convertToDatabaseColumn(String attribute) {
        return EncryptionUtil.getInstance().encrypt(attribute);
    }

    @Override
    public String convertToEntityAttribute(String dbData) {
        return EncryptionUtil.getInstance().decrypt(dbData);
    }
}

方案3:检查EntityManager的扫描范围

确保LocalContainerEntityManagerFactoryBean的packages方法包含了EncryptionConverter所在的包,否则Hibernate无法识别并使用该转换器:

builder.packages("com.yourproject.entity", "com.yourproject.converter")
关键注意事项
  • 双数据库的两个EntityManagerFactory都需要配置Converter,否则其中一个库的实体转换会失败。
  • 优先使用方案1,它更符合Spring的依赖注入规范,避免静态实例带来的潜在问题。
  • 避免使用字段注入(@Autowired直接标记字段),改用构造器注入,减少Spring代理相关的问题。

内容的提问来源于stack exchange,提问作者shivamx96

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 04:13:10