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

DataSource实例化失败:Spring Boot连接MSSQL的JPA配置问题

MSSQL数据库JPA连接Bean实例化空指针异常排查方案

问题概述

连接外部MSSQL数据库时触发Bean实例化空指针异常,已尝试添加@EnableJpaRepositories注解、排除DataSourceAutoConfiguration,MyBatis可正常连接但业务要求使用JPA。相关配置及异常堆栈如下:

配置文件(application.yml)

ansir.datasource:
  schema: schema
  jdbc-url: jdbc:sqlserver://SERVER:PORTNO;databaseName=DB;encrypt=false 
  username: root
  password: pwd
  driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
  hikari.maximum-pool-size: 10
  hikari.pool-name: HikariPool-ANSIR
  jpa:
    show-sql: true
    hibernate.dialect: org.hibernate.dialect.SQLServer2012Dialect
    hibernate.ddl-auto: none

自定义配置类(ANSIRConfiguration.java)

@Value("${ansir.datasource}")
private String SCHEMA_NAME;

@Value("${ansir.datasource.jdbc-url}")
private String jdbcUrl;

@Value("${ansir.datasource.username}")
private String username;

@Value("${ansir.datasource.password}")
private String password;

@Value("${ansir.datasource.driver-class-name}")
private String driverClassName;

@Value("${ansir.datasource.hikari.maximum-pool-size}")
private String maxPool;

@Value("${ansir.datasource.hikari.pool-name}")
private String poolName;

@Value("${ansir.datasource.jpa.show-sql}")
private String showSql;

@Value("${ansir.datasource.jpa.hibernate.dialect}")
private String hibernateDialect;

@Value("${ansir.datasource.jpa.hibernate.ddl-auto}")
private String ddl;
private final Environment env;

@Autowired
public ANSIRConfiguration(Environment env) {
    this.env = env;
}

@Bean
@ConfigurationProperties("ansir.datasource")
public DataSource ansirDataSource() {
    return DataSourceBuilder.create()
            .driverClassName(env.getProperty(driverClassName))
            .url(env.getProperty(jdbcUrl))
            .username(env.getProperty(username))
            .password(env.getProperty(password))
            .build();
}

@Bean
public PlatformTransactionManager ansirTransactionManager(@Qualifier("ansirEntityManager") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {

    JpaTransactionManager transactionManager
            = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(
            entityManagerFactoryBean.getObject());
    return transactionManager;
}


@Bean("ansirEntityManager")
public LocalContainerEntityManagerFactoryBean ansirEntityManager(@Qualifier("ansirDataSource")DataSource ansirDataSource) {
    LocalContainerEntityManagerFactoryBean entityManagerFactory
            = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactory.setDataSource(ansirDataSource);
    entityManagerFactory.setPackagesToScan("com.autonation.ca.client.ansir.entity");
    entityManagerFactory.setPersistenceUnitName("ansir");

    HibernateJpaVendorAdapter vendorAdapter

            = new HibernateJpaVendorAdapter();
    entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
    HashMap<String, Object> properties = new HashMap<>();
    properties.put("hibernate.hbm2ddl.auto",
            env.getProperty(ddl));
    properties.put("hibernate.dialect",
            env.getProperty(hibernateDialect));
    properties.put("hibernate.proc.param_null_passing", true);
    properties.put("hibernate.show_sq", showSql);
    entityManagerFactory.setJpaPropertyMap(properties);

    return entityManagerFactory;
}

异常堆栈

Caused by: java.lang.NullPointerException: null
at java.base/java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)
at java.base/java.util.concurrent.ConcurrentHashMap.putIfAbsent(ConcurrentHashMap.java:1541)
at java.base/java.lang.ClassLoader.getClassLoadingLock(ClassLoader.java:667)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:591)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at com.zaxxer.hikari.HikariConfig.attemptFromContextLoader(HikariConfig.java:970)
at com.zaxxer.hikari.HikariConfig.setDriverClassName(HikariConfig.java:480)
at org.springframework.boot.jdbc.DataSourceBuilder$MappedDataSourceProperty.set(DataSourceBuilder.java:460)
at org.springframework.boot.jdbc.DataSourceBuilder$MappedDataSourceProperties.set(DataSourceBuilder.java:355)
at org.springframework.boot.jdbc.DataSourceBuilder.build(DataSourceBuilder.java:190)
at com.autonation.ca.client.ansir.config.ANSIRConfiguration.ansirDataSource(ANSIRConfiguration.java:64)
...

问题根源及修复方案

从堆栈分析,空指针出现在HikariCP加载驱动类时,核心问题集中在配置类的属性注入与DataSource构建逻辑错误:

1. 数据源构建逻辑错误

ansirDataSource()方法中,错误地使用env.getProperty(driverClassName)——driverClassName已经是通过@Value注入的驱动类全名(如com.microsoft.sqlserver.jdbc.SQLServerDriver),而非配置文件的key(ansir.datasource.driver-class-name),调用env.getProperty会返回null,导致Hikari无法加载驱动类。

修复:
直接使用已注入的属性值,无需再通过env.getProperty获取:

@Bean
// 移除@ConfigurationProperties,避免与手动配置冲突,或完全依赖自动绑定
public DataSource ansirDataSource() {
    return DataSourceBuilder.create()
            .driverClassName(driverClassName)
            .url(jdbcUrl)
            .username(username)
            .password(password)
            .build();
}

若要使用@ConfigurationProperties自动绑定Hikari配置,可简化为:

@Bean
@ConfigurationProperties("ansir.datasource")
public DataSource ansirDataSource() {
    return DataSourceBuilder.create().build();
}

此时无需手动设置url、username等属性,Spring会自动绑定配置文件中ansir.datasource下的所有属性。

2. @Value注入错误

@Value("${ansir.datasource}")试图注入整个数据源对象,而非指定的schema属性,应改为:

@Value("${ansir.datasource.schema}")
private String SCHEMA_NAME;

3. JPA属性拼写错误

EntityManager配置中hibernate.show_sq拼写错误,应为hibernate.show_sql,否则SQL日志配置不生效:

properties.put("hibernate.show_sql", showSql);

4. 事务管理器初始化风险

直接调用entityManagerFactoryBean.getObject()可能导致EntityManagerFactory未完成初始化,应改为注入EntityManagerFactory:

@Bean
public PlatformTransactionManager ansirTransactionManager(@Qualifier("ansirEntityManager") EntityManagerFactory entityManagerFactory) {
    return new JpaTransactionManager(entityManagerFactory);
}

5. JPA属性获取冗余

已通过@Value注入ddl、hibernateDialect等属性,无需再调用env.getProperty,直接使用注入值即可:

properties.put("hibernate.hbm2ddl.auto", ddl);
properties.put("hibernate.dialect", hibernateDialect);

最终修复后的配置类示例

@Configuration
@EnableJpaRepositories(basePackages = "com.autonation.ca.client.ansir.repository",
        entityManagerFactoryRef = "ansirEntityManager",
        transactionManagerRef = "ansirTransactionManager")
public class ANSIRConfiguration {

    @Value("${ansir.datasource.schema}")
    private String SCHEMA_NAME;

    @Value("${ansir.datasource.jdbc-url}")
    private String jdbcUrl;

    @Value("${ansir.datasource.username}")
    private String username;

    @Value("${ansir.datasource.password}")
    private String password;

    @Value("${ansir.datasource.driver-class-name}")
    private String driverClassName;

    @Value("${ansir.datasource.jpa.show-sql}")
    private String showSql;

    @Value("${ansir.datasource.jpa.hibernate.dialect}")
    private String hibernateDialect;

    @Value("${ansir.datasource.jpa.hibernate.ddl-auto}")
    private String ddl;

    @Bean
    public DataSource ansirDataSource() {
        return DataSourceBuilder.create()
                .driverClassName(driverClassName)
                .url(jdbcUrl)
                .username(username)
                .password(password)
                .build();
    }

    @Bean
    public PlatformTransactionManager ansirTransactionManager(@Qualifier("ansirEntityManager") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    @Bean("ansirEntityManager")
    public LocalContainerEntityManagerFactoryBean ansirEntityManager(@Qualifier("ansirDataSource") DataSource ansirDataSource) {
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setDataSource(ansirDataSource);
        entityManagerFactory.setPackagesToScan("com.autonation.ca.client.ansir.entity");
        entityManagerFactory.setPersistenceUnitName("ansir");

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        entityManagerFactory.setJpaVendorAdapter(vendorAdapter);

        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.auto", ddl);
        properties.put("hibernate.dialect", hibernateDialect);
        properties.put("hibernate.proc.param_null_passing", true);
        properties.put("hibernate.show_sql", showSql);
        entityManagerFactory.setJpaPropertyMap(properties);

        return entityManagerFactory;
    }
}

额外注意事项

  • 确保主启动类排除默认数据源自动配置:@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
  • 确认MSSQL驱动依赖已正确引入(如com.microsoft.sqlserver:mssql-jdbc)
  • 若使用多数据源,需确保@EnableJpaRepositories指定对应的repository包、entityManagerFactory和transactionManager引用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:59:17