Here are two possible solutions.
Extend SqlSessionFactory
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import org.apache.log4j.Logger;
public class CustomSqlSessionFactory extends DefaultSqlSessionFactory
{
private static Logger msLogger = Logger.getLogger(CustomSqlSessionFactory.class);
public CustomSqlSessionFactory(Configuration configuration)
{
super(configuration);
}
@Override
public SqlSession openSession()
{
SqlSession session = super.openSession();
alterSession(session);
return session;
}
protected void alterSession(SqlSession session)
{
try
{
Statement statement = session.getConnection().createStatement();
statement.addBatch("alter session set nls_date_format = 'yyyy/mm/dd hh24:mi:ss'");
statement.addBatch("ALTER SESSION SET NLS_COMP = LINGUISTIC");
statement.addBatch("ALTER SESSION SET NLS_SORT = XTURKISH_AI");
statement.executeBatch();
msLogger.debug("Altered newly created session parameters.");
statement.close();
}
catch (SQLException e)
{
msLogger.error("Alter session failed!", e);
}
}
@Override
public SqlSession openSession(boolean autoCommit)
{
SqlSession session = super.openSession(autoCommit);
alterSession(session);
return session;
}
@Override
public SqlSession openSession(Connection connection)
{
SqlSession session = super.openSession(connection);
alterSession(session);
return session;
}
@Override
public SqlSession openSession(ExecutorType execType)
{
SqlSession session = super.openSession(execType);
alterSession(session);
return session;
}
@Override
public SqlSession openSession(ExecutorType execType, boolean autoCommit)
{
SqlSession session = super.openSession(execType, autoCommit);
alterSession(session);
return session;
}
@Override
public SqlSession openSession(ExecutorType execType, Connection connection)
{
SqlSession session = super.openSession(execType, connection);
alterSession(session);
return session;
}
@Override
public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)
{
SqlSession session = super.openSession(execType, level);
alterSession(session);
return session;
}
@Override
public SqlSession openSession(TransactionIsolationLevel level)
{
SqlSession session = super.openSession(level);
alterSession(session);
return session;
}
}
If you are using spring also create a CustomSqlSessionFactoryBuilder
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class CustomSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder
{
@Override
public SqlSessionFactory build(Configuration config)
{
return new CustomSqlSessionFactory(config);
}
}
and attach CustomSqlSessionFactoryBuilder by modifying the SqlSessionFactoryBean configuration
<bean id="mySqlSessionFactoryBuilder" class="your.package.CustomSqlSessionFactoryBuilder" />
<bean id="mySessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="sqlSessionFactoryBuilder" ref="mySqlSessionFactoryBuilder" />
</bean>
Session will be altered on each borrow operation. However, if you are using pooled connection, this approach will degrade the execution performance. Hence on every checkout of the connection from the pool, openSession will be called.
If you are using a pooled data source then handling session alter operations on data source level will be much faster. Second solution modifies C3P0 pooled data source for altering session.
Modify Pooled Data Source (C3P0 and Spring)
Create a connection customizer class [1]
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.log4j.Logger;
import com.mchange.v2.c3p0.AbstractConnectionCustomizer;
public class ConnectionCustomizer extends AbstractConnectionCustomizer
{
private static Logger msLogger = Logger.getLogger(ConnectionCustomizer.class);
public void onAcquire(Connection c, String pdsIdt)
{
try
{
Statement statement = c.createStatement();
statement.addBatch("alter session set nls_date_format = 'yyyy/mm/dd hh24:mi:ss'");
statement.addBatch("ALTER SESSION SET NLS_COMP = LINGUISTIC");
statement.addBatch("ALTER SESSION SET NLS_SORT = XTURKISH_AI");
statement.executeBatch();
msLogger.debug("Altered newly created session parameters.");
statement.close();
}
catch (SQLException e)
{
msLogger.error("Alter session failed!", e);
}
}
}
Modify data source configuration bean and add created class as connectionCustomizerClassName
<!--
driverClass : Driver class that will be used to connect to database.
jdbcUrl : jdbc url defining the database connection string.
user : username of the database user.
password : password of the database user.
acquireIncrement : how many connections will be created at a time when there will be a shortage of connections.
idleConnectionTestPeriod : after how much delay a connection will be closed if it is no longer in use.
maxPoolSize : Max number of connections that can be created.
maxStatements : Max number of SQL statements to be executed on a connection.
minPoolSize : Minimum number of connections to be created.
connectionCustomizerClassName : Custom connection customizer to enable session alterations and jobs on acquiring/closing - checking in/out physical connections
-->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="${app.jdbc.url}" />
<property name="user" value="${app.jdbc.username}" />
<property name="password" value="${app.jdbc.password}" />
<property name="acquireIncrement" value="3" />
<property name="maxPoolSize" value="50" />
<property name="maxStatements" value="50" />
<property name="minPoolSize" value="5" />
<property name="idleConnectionTestPeriod" value="60" />
<property name="preferredTestQuery" value="SELECT 1 FROM DUAL" />
<property name="testConnectionOnCheckout" value="true" />
<property name="connectionCustomizerClassName" value="your.package.name.ConnectionCustomizer" />
</bean>
[1]: http://www.mchange.com/projects/c3p0/