14

My Enviroment

  • Java 5
  • Spring 2.5.5
  • DBCP DataSource (org.apache.commons.dbcp.BasicDataSource)
  • MySQL

Similar posts

Links

My Problem

  • I need to set on my connection the timezone, aiming to prevent the conversions when dealing with TIMESTAMP columns.

My Idea/research

  • DBCP Connection Pool did not mention anything around timezone. LINK

  • What I investigate and thought that was oK is described on THIS post, exemplifying is:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="URL" value="${database.url}" /> 
    <property name="user" value="${database.username}" /> 
    <property name="password" value="${database.passwd}" /> 
    <property name="connectionCachingEnabled" value="true"/>
    <property name="sessionTimeZone" value="GMT-3"/>
</bean>

Asking for help area :)

  • But this is not working!!
  • What I want here is a simple way, preferentially using Spring to configure the timezone on jdbc connection.

Thanks in advance for any help/tips/advice/knowledge share


SOLUTION:

My Solution was based on tips collected on this post! Thanks for all!

(...)
@Override
public Connection getConnection() {
    Connection conn = null;
    Statement statement = null;
    try {
        conn = super.getConnection();
        statement = conn.createStatement();
        statement.execute("SET time_zone = \'" + timezone+"\'");
    } catch (SQLException e) {
        LOG.fatal("Error while SET time_zone", e);
    } finally {
        try {
            statement.close();
        } catch (SQLException e) {
            LOG.warn("Error while closing statement", e);
        }
    }
    if(LOG.isDebugEnabled())
        LOG.debug("SET time_zone("+timezone+") for connection, succeed!");
    return conn;
}
(...)

and on my Spring configuration file:

<bean id="dataSource" class="com.my.package.dbcp.TimezoneEnabledDataSource" destroy-method="close">
    (...)
    <property name="timezone" value="${database.timezone}" />
    (...)
</bean>

I hope this post can help someone in the future. Any question ping me!

Community
  • 1
  • 1
rafa.ferreira
  • 1,997
  • 7
  • 26
  • 41
  • are you certain that GMT-3 is recognized? Have you tried `America/Los_Angeles` for example (for the sake of testing) – Bozho May 11 '11 at 21:50
  • I'll keep updating my post with all my finds! I've just quit about find something regarding DBCP configurations! – rafa.ferreira May 11 '11 at 21:50
  • @Bozho, I'll double check in some hours that I'm not @ home but as peer the link I mention the error is complaining about the property( Invalid property 'sessionTimeZone'), not the value for it. – rafa.ferreira May 11 '11 at 21:52

4 Answers4

7

You should be able to put the same SQL statements in the initConnectionSqls property of the DBCP configuration element. Just add this to the DBCP configuration element

<property name="initConnectionSqls" value="SET time_zone = '${database.timezone}'"/>

Depending on your version of DBCP, you may have to use connectionInitSqls as the property name. This information is straight from DBCP configuration documentation.

Chandranshu
  • 3,669
  • 3
  • 20
  • 37
  • For Oracle, the query could be: alter session set time_zone= ''${database.timezone} – LMC May 13 '16 at 18:08
6

If the data source doesn't have such a property, you can extend it and add that property:

public TimezoneEnabledDataSource extends BasicDataSource {
    private String timezone;
    //getter and setter for it

    @Override    
    public Connection getConnection() {
        Connection c = super.getConnection();
        // execute a query: SET time_zone = '-8:00'
        return c;
    }
}

See here http://www.electrictoolbox.com/mysql-set-timezone-per-connection/ for the query details.

MySQL documentation writes:

Per-connection time zones. Each client that connects has its own time zone setting, given by the session time_zone variable. Initially, the session variable takes its value from the global time_zone variable, but the client can change its own time zone with this statement:

mysql> SET time_zone = timezone;

You can also check if c3p0 doesn't have something built-in.

Community
  • 1
  • 1
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • @Bozho, this looks like a solution!!! I'll focus some time on this! Did you see any problem by doing this kind of solution!? – rafa.ferreira May 11 '11 at 22:04
  • it's from the top of my head. I don't actually see a problem, but I haven't used it in production ;) – Bozho May 11 '11 at 22:06
  • I don't think it is a good idea to define some properties in your database in a multithreaded enviroment :S – Vincent Devillers May 11 '11 at 22:15
  • @Treydone I didn't understand your comment. I think the query sets the timezone per connection, not globally (at least that's what the article claims) – Bozho May 11 '11 at 22:25
  • @Treydone what are your concerns about it? I'm asserting that when works with timestamp columns, MySQL will not change my date due to different timezones. Thinking that MySQL will always be started at UTC. – rafa.ferreira May 12 '11 at 02:31
  • @Bozho: You are setting global properties in the database using the SET command on each call of getConnection(). This have to be done just once, maybe using the "init-method" in the Spring XML configuration, don't you think? – Vincent Devillers May 12 '11 at 07:42
  • @Treydone could you show a refeference in the documentation that confirms that? From the article I linked it follows that this `SET` is per-connection (as is the case with `SET NAMES` for example). – Bozho May 12 '11 at 07:45
  • Actually, I found a quote confirming it is per-connection – Bozho May 12 '11 at 07:46
  • You didn't understand that I said: you are executing a SET query in your database, just to have a connection. But you are using a connection pool, so even if the connection had the good time zone setting, you are querying the database again to call the SET... So for your solution, it will better doing "SET GLOBAL time_zone = timezone;" at the initialization of the datasource than calling "SET time_zone = timezone;" on each getConnection(). – Vincent Devillers May 12 '11 at 08:17
  • again, I didn't understand. why would it be calling `SET GLOBAL`? – Bozho May 12 '11 at 08:20
  • @Bozho, what I think that @Treydone is trying to say is: Instead of set timezone for each connection we can set the global value, that all connection shall inherit. As peer my understanding we have on MySQL (SYSTEM_TIMEZONE > GLOBAL_TIMEZONE > SESSION_TIMEZONE), each smaller inherit the bigger one! But to set any GLOBAL variable I need to have SUPER credentials. – rafa.ferreira May 12 '11 at 14:28
  • Mark this as solution. I did here on my stuffs and works! Thanks for all! – rafa.ferreira May 16 '11 at 18:44
  • @Bozho, I was trying to test this class as I'm used to it, but I'm suffering on this! No founds about how to mock my superclass. Any clue/tip on this!? Thinking in a different way to build this class trying to inject BasicDataSource, but for that I'll have to create all methods and forward to a local instance of BasicDataSource injected and don't seems to be the correct way! – rafa.ferreira May 17 '11 at 21:30
0

One of the possible solutions:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="URL" value="${database.url}?serverTimezone=America/Los_Angeles" /> 
    <property name="user" value="${database.username}" /> 
    <property name="password" value="${database.passwd}" /> 
    <property name="connectionCachingEnabled" value="true"/>
    <property name="sessionTimeZone" value="GMT-3"/>
</bean>
-1

There is no "sessionTimeZone" member in the BasicDataSource. Use C3P0 which is a "better" connection pool than DBCP, or even better, if you are in a Java EE web server, use it to initialize a JNDI datasource ;)

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Vincent Devillers
  • 1,628
  • 1
  • 11
  • 17
  • Hi Treydone, thanks for your help. I saw somewhere that is possible to configure that using C3P0, but I don't know if is a option, keeping in mind that is a huge system very solid. But I'll look for your solution! – rafa.ferreira May 11 '11 at 22:01
  • 2
    Interestingly enough there is no sessionTimeZone or equivalent member in C3P0 DataSources either... – Nicholi Feb 11 '12 at 00:28