PostgreSQL手动创建HikariDataSource解决报错Cannot commit when autoCommit is enabled

PostgreSQL创建HikariDataSource解决报错autoCommit


在这里插入图片描述

问题

  • 项目是使用jhipster构建的,使用liquibase管理数据库连接
  • 我们使用的PostgreSQL数据库,由于业务需要,需要新增一个ClickHouse数据库,但是这样两个DataSource导致程序出错

解决

  • 首先,想的是对PostgreSQL数据库连接,显式声明。在DatabaseConfiguration里,显式声明@Bean("springDataSource")并设置@Primary,优先加载使用pg
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;

@Configuration
@EnableJpaRepositories({ "com.xxx.analysis.repository" })
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
@EnableTransactionManagement
public class DatabaseConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(DatabaseConfiguration.class);

    /**
     * PG数据源
     * 由于手动注入了CK数据源,所以需要在这里显式声明PG数据源优先为springDataSource
     * @param properties yml里的数据源配置
     * @return dataSource
     */
    @Primary //默认优先选择
    @Bean("springDataSource") //注入springDataSource对象
    @ConfigurationProperties(prefix = "spring.datasource") //注入dspringDataSource对象读取配置文件,spring.datasource为前缀,之后字段和实体类的属性一致进行匹配诸如内容
    public DataSource dataSource(DataSourceProperties properties) {
        logger.info("init master data source:{}", properties.determineDatabaseName());
        return DataSourceBuilder.create().build();
    }
}

  • 这样程序启动没有报错了,但是使用起来有问题,报错org.springframework.orm.jpa.JpaSystemException: Unable to commit against JDBC Connection; nested exception is org.hibernate.TransactionException: Unable to commit against JDBC Connection
Caused by: org.hibernate.TransactionException: Unable to commit against JDBC Connection
	at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.commit(AbstractLogicalConnectionImplementor.java:92)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:282)
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562)
	... 155 common frames omitted
Caused by: org.postgresql.util.PSQLException: Cannot commit when autoCommit is enabled.
	at org.postgresql.jdbc.PgConnection.commit(PgConnection.java:872)
	at com.zaxxer.hikari.pool.ProxyConnection.commit(ProxyConnection.java:387)
	at com.zaxxer.hikari.pool.HikariProxyConnection.commit(HikariProxyConnection.java)
	at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.commit(AbstractLogicalConnectionImplementor.java:86)
	... 158 common frames omitted
  • 改为使用注解声明后,autoCommit没生效,调试了下发现DataSourceProperties只接收部分参数,而autoCommit没在里面
  • 没办法,只好自己接收参数,自己创建连接初始化HikariDataSource 了,最终配置和代码如下

配置文件

spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    url: jdbc:postgresql://192.168.1.50:5432/june
    username: postgres
    password: postgres
    hikari:
      poolName: Hikari
      autoCommit: false
      maximum-pool-size: 100
      connection-timeout: 60000
      idle-timeout: 400000
      minimum-idle: 10
      max-lifetime: 480000
      connection-test-query: SELECT 1

代码

package com.xxx.analysis.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;

@Configuration
@EnableJpaRepositories({ "com.xxx.analysis.repository" })
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
@EnableTransactionManagement
public class DatabaseConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(DatabaseConfiguration.class);

    @Value("${spring.datasource.hikari.poolName}")
    private String poolName;

    @Value("${spring.datasource.hikari.autoCommit}")
    private boolean autoCommit;

    @Value("${spring.datasource.hikari.connection-timeout}")
    private Integer connectionTimeout;

    @Value("${spring.datasource.hikari.idle-timeout}")
    private Integer idleTimeout;

    @Value("${spring.datasource.hikari.max-lifetime}")
    private Integer maxLifetime;

    @Value("${spring.datasource.hikari.minimum-idle}")
    private Integer minimumIdle;

    @Value("${spring.datasource.hikari.maximum-pool-size}")
    private Integer maximumPoolSize;

    @Value("${spring.datasource.hikari.connection-test-query}")
    private String connectionTestQuery;

    /**
     * PG数据源
     * 由于手动注入了CK数据源,所以需要在这里显式声明PG数据源优先为springDataSource
     * @param properties yml里的数据源配置
     * @return dataSource
     */
    @Primary //默认优先选择
    @Bean("springDataSource") //注入springDataSource对象
    @ConfigurationProperties(prefix = "spring.datasource") //注入springDataSource对象读取配置文件,spring.datasource为前缀,之后字段和实体类的属性一致进行匹配诸如内容
    public DataSource dataSource(DataSourceProperties properties) {
        HikariDataSource dataSource = new HikariDataSource(getConfig(properties));
        if (StringUtils.hasText(properties.getName())) {
            dataSource.setPoolName(properties.getName());
        }
        return dataSource;
    }

    /**
     * 根据yml配置设置HikariConfig
     * @param properties
     * @return
     */
    private HikariConfig getConfig(DataSourceProperties properties) {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(properties.getUrl());
        hikariConfig.setUsername(properties.getUsername());
        hikariConfig.setPassword(properties.getPassword());

        hikariConfig.setMaximumPoolSize(maximumPoolSize);
        hikariConfig.setConnectionTestQuery(connectionTestQuery);
        hikariConfig.setPoolName(poolName);
        hikariConfig.setAutoCommit(autoCommit);
        hikariConfig.setConnectionTimeout(connectionTimeout);
        hikariConfig.setIdleTimeout(idleTimeout);
        hikariConfig.setMaxLifetime(maxLifetime);
        hikariConfig.setMinimumIdle(minimumIdle);

        hikariConfig.addDataSourceProperty("dataSource.cachePrepStmts", "true");
        hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSize", "250");
        hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSqlLimit", "2048");
        hikariConfig.addDataSourceProperty("dataSource.useServerPrepStmts", "true");

        return hikariConfig;
    }

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坚持是一种态度

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值