4

I have this configuration in ibatis-config.xml

<configuration>
    <properties resource="collector.properties"/>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${dev.jdbc.driver}" />
                <property name="url" value="${dev.jdbc.url}" />
            </dataSource>
        </environment>
        <environment id="test">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${test.jdbc.driver}" />
                <property name="url" value="${test.jdbc.url}" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
    </mappers>
</configuration>

As shown it will load datasource from <environment id="development">

QUESTION: Is it possible at run time switch to use <environment id="test"> without modifying XML? For example - I have a test file where I'm using SqlSessionFactory and want to set it programmatically to use test environment?

Bostone
  • 36,858
  • 39
  • 167
  • 227
  • Ideally you should use a build tool and project structure so that this is not an issue. I recommend maven, it can be a little confusing and magical at first but when you get past that it will save a ton of time and enforce some good practices. – nash Dec 08 '11 at 22:18

2 Answers2

8

SqlSessionFactoryBuilder.build() method can select a specific environment in XML.

For example,

private Reader reader;
private SqlSessionFactory sqlSessionFactorys;
private SqlSession session;

reader = Resources.getResourceAsReader("ibatis-config.xml");

sqlSessionFactorys = new SqlSessionFactoryBuilder().build(reader, "test");
testSession = sqlSessionFactorys.openSession(); // test env

sqlSessionFactorys = new SqlSessionFactoryBuilder().build(reader, "development");
devSession = sqlSessionFactorys.openSession(); // dev env
fishjd
  • 1,617
  • 1
  • 18
  • 31
Alex Park
  • 157
  • 7
2

According to this site: http://codenav.org/code.html?project=/org/mybatis/mybatis/3.2.5&path=/Source%20Packages/org.apache.ibatis.session/SqlSessionFactoryBuilder.java

The build() method closes the reader/inputstream before returning SqlSessionFactory now. So you will need to open a new reader/stream in order to load the second session. I discovered this when I separated out my account/security tables to a separate database from the main application DB. My first go around I kept getting errors when the bean was trying to load the session factory due to an input stream error (closed).

e.g.

try {
    inputStream = Resources.getResourceAsStream(MYBATIS_CONFIG_PATH);
    prodDbSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, prodDbEnvironment);
    inputStream = Resources.getResourceAsStream(MYBATIS_CONFIG_PATH);
    securityDbSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, securityDbEnvironment);
} catch (IOException ex) {
    String msg = "Unable to get SqlSessionFactory";
    CustomizedLogger.LOG(Level.SEVERE, this.getClass().getCanonicalName(), "methodName", msg, ex);
}

Although I put them in separate try catch blocks so that I know which one failed specifically right away in the log file.

I also implement this as a singleton so that it only has to load load resources once.

Context: I run this in a Java EE container and use MyBatis for straight forward queries and for where I would use native queries since it is a much simpler and straight forward framework. I might switch to using it over JPA everywhere, but that is still up for debate.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Bill Rosmus
  • 2,941
  • 7
  • 40
  • 61