4

I'm trying to setup c3p0 on my spring boot server. This is my config right now

spring.datasource.url=jdbc:mysql://url/db
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.test-on-borrow=true
#spring.datasource.test-while-idle=true
spring.datasource.validation-query=SELECT 1
#spring.datasource.time-between-eviction-runs-millis=10000
#spring.datasource.min-evictable-idle-time-millis=30000

spring.jpa.show-sql=true

spring.jpa.properties.hibernate.globally_quoted_identifiers=true
spring.jpa.properties.hibernate.connection.provider_class=org.hibernate.connection.C3P0ConnectionProvider
spring.jpa.properties.hibernate.connection.driver_class=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.connection.url=jdbc:mysql://url/db
spring.jpa.properties.hibernate.connection.username=username
spring.jpa.properties.hibernate.connection.password=password
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.show_sql=true
#spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop


spring.jpa.properties.hibernate.c3p0.max_size=30
spring.jpa.properties.hibernate.c3p0.min_size=7
spring.jpa.properties.hibernate.c3p0.acquire_increment=1
spring.jpa.properties.hibernate.c3p0.idle_test_period=100
spring.jpa.properties.hibernate.c3p0.max_statements=0
spring.jpa.properties.hibernate.c3p0.max_idle_time=200
spring.jpa.properties.hibernate.c3p0.url=jdbc:mysql://url/db
spring.jpa.properties.hibernate.c3p0.username=username
spring.jpa.properties.hibernate.c3p0.password=password
spring.jpa.properties.hibernate.c3p0.driverClassName=com.mysql.jdbc.Driver

My problem is that I can't figure out how to tell spring.datasource to use

com.mchange.v2.c3p0.ComboPooledDataSource

All XML definitions I saw use something along the lines of

<bean id="dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource">

Is it not possible to set the datasource type/class in application.properties?

According to this

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc

there is

spring.datasource.type= # fully qualified name of the connection pool implementation to use

but according to this

http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

(and to my STS) the .type option doesn't exist. Is this a bug or am I supposed to use this differently?

Your help will be much appreciated!

Cheers!

RVP
  • 2,330
  • 4
  • 23
  • 34
  • Your `spring.jpa.properties.hibernate.connection` and `spring.jpa.properties.hibernate.c3p0` are useless. Spring Boot will inject a datasource which in turn disables the use of these properties, hence they do nothing but add space to your `application.properties`. I would not recommend the usage of C3P0 it is quite old and has some flaws instead use one of the default supported once like `tomcat-jdbc` or `HikariCP`. That way it is simply a matter of adding the jar and Spring Boot will configure it for you. – M. Deinum Sep 29 '15 at 05:43
  • The property you are looking for is for Spring Boot 1.3 earlier versions don't have this. – M. Deinum Sep 29 '15 at 05:44

2 Answers2

6

spring.datasource.type has been introduced in the 1.3 line so you need Spring Boot 1.3.0.M5 to use that property (content assistance in your IDE should have give you the proper hint).

On 1.2.x you need to create the DataSource bean yourself to force the type, something like

@Bean
@ConfigurationProperties("spring.datasource")
public DataSource dataSource() {
   return DataSourceBuilder.create().type(ComboPooledDataSource.class)
            .build();
}
Stephane Nicoll
  • 31,977
  • 9
  • 97
  • 89
1

You guys hit the nail on the head. I did my manual setup configuration this morning and hooked up c3p0 but then for one of my controllers I was using jdbcTemplate and it turned out the c3p0 datasource cannot be used with jdbcTemplates so I decided to take a look at the alternatives.

I did some reading and it turned out the tomcat-jdbc pool would be the best option for my case. So to set this up I removed all properties from application.properties that I listed in the original post and added the following custom ones

tomcat.jdbc.pool.url=jdbc:mysql://url/db_name
tomcat.jdbc.pool.username=username
tomcat.jdbc.pool.password=password
tomcat.jdbc.pool.initial-size=10
tomcat.jdbc.pool.test-on-borrow=true
tomcat.jdbc.pool.test-while-idle=true
tomcat.jdbc.pool.validation-query=SELECT 1
tomcat.jdbc.pool.driver-class-name=com.mysql.jdbc.Driver
tomcat.jdbc.pool.max_size=30
tomcat.jdbc.pool.min_size=7

I then created the following configuration class to setup my primary datasource as a org.apache.tomcat.jdbc.pool.DataSource

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;


@EnableTransactionManagement
@Configuration
public class DataSourceConfiguration {

    @Value("${tomcat.jdbc.pool.max_size}")
    private int maxSize;

    @Value("${tomcat.jdbc.pool.min_size}")
    private int minSize;

    @Value("${tomcat.jdbc.pool.initial-size}")
    private int initialSize;

    @Value("${tomcat.jdbc.pool.test-on-borrow}")
    private boolean testOnBorrow;

    @Value("${tomcat.jdbc.pool.test-while-idle}")
    private boolean testWhileIdle;

    @Value("${tomcat.jdbc.pool.username}")
    private String username;

    @Value("${tomcat.jdbc.pool.password}")
    private String password;

    @Value("${tomcat.jdbc.pool.url}")
    private String url;

    @Value("${tomcat.jdbc.pool.driver-class-name}")
    private String driverClassName;

    @Value("${tomcat.jdbc.pool.validation-query}")
    private String validationQuery;

    @Bean
    @Primary
    public DataSource dataSource() {
        DataSource dataSource = new DataSource();
        dataSource.setUrl(url);
        dataSource.setPassword(password);
        dataSource.setUsername(username);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setValidationQuery(validationQuery);
        dataSource.setInitialSize(initialSize);
        dataSource.setMaxIdle(maxSize);
        dataSource.setMinIdle(minSize);
        dataSource.setTestOnBorrow(testOnBorrow);
        dataSource.setTestWhileIdle(testWhileIdle);
        return dataSource;
    }
}

And voila, I now have a production-ready connection pool.

I read that HikariCP would probably outperform tomcat-jdbc on some occasions BUT my app is a custom request from a business and it would only be used by 5-10-20 people at a time so ease of configuration and setup definitely outweighed the minuscule performance gains.

Hope this helps someone.

RVP
  • 2,330
  • 4
  • 23
  • 34