是使用Spring jdbcTemplates线程安全的

时间:2017-09-16 14:19:12

标签: java spring multithreading jdbc

我有自己的DAO,它扩展了NamedJdbcDaoSupport。这个DAO是使用Spring框架创建的。

我编写了一个小型测试应用程序,可以从主线程多次访问DAO而无需等待。

在这种情况下一切正常。

但是如果我从不同的线程访问DAO,我收到以下NPE:

java.lang.NullPointerException
    at org.springframework.jdbc.core.PreparedStatementCreatorFactory$PreparedStatementCreatorImpl.createPreparedStatement(PreparedStatementCreatorFactory.java:238)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:627)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:684)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:711)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:761)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:192)
    at test.DAO.loadData(DAO.java:29)
    at test.Application$1.run(Application.java:19)
    at java.lang.Thread.run(Unknown Source)

在NamedJdbcDaoSupport的描述中有以下注释:

  

“注意:配置后,此类的实例是线程安全的。”

那我为什么要收到这个NPE?如果我进入Spring源代码,我可以看到DBConnection似乎是null。但为什么?通常,如果Spring无法从连接池获得连接,则返回SQLException。所以永远不可能有NPE。

有人可以帮助我理解为什么NamedJdbcDaoSupport不是线程安全的,尽管有其他意见。我能做什么?

这是我的申请:

public class Application {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("ServerContext.xml");

        DAO bean = (DAO)classPathXmlApplicationContext.getBean("dao");


        for (int i = 0; i < 100; i++) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    for (int j = 0; j < 100; j++) {
                        bean.loadData();
                    }
                }
            }).start();
        }
    }

}

这是我的gradle脚本:

    repositories {
    mavenCentral()
}

dependencies {
   compile group: 'org.springframework', name: 'spring-context', version: '4.3.11.RELEASE'
    compile 'org.springframework:spring-jdbc:4.3.11.RELEASE'
        compile 'commons-dbcp:commons-dbcp:1.4'
        compile files('lib/ojdbc6.zip')
}

这是我的DAO:

public class DAO extends NamedParameterJdbcDaoSupport {

    public List<String> loadData() {
        Date fromDate = null;
        Date toDate = null;
        MapSqlParameterSource namedParameters = new MapSqlParameterSource();
        namedParameters.addValue("fromDate", fromDate);
        namedParameters.addValue("toDate", toDate);
        String sql = "SELECT * FROM myTable";
        return getNamedParameterJdbcTemplate().query(sql, namedParameters, new RowMapper<String>() {
            @Override
            public String mapRow(ResultSet rs, int rowNum) throws SQLException {

                return null;
            }
        });
    }

}

这是我的春天背景:

<!-- Database -->
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
    <property name="URL" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
    <property name="user" value="user"/>
    <property name="password" value="passwort"/>
    <property name="connectionCachingEnabled" value="true" />    
    <property name="connectionCacheName" value="my_connection_pool" />
    <property name="connectionCacheProperties">
        <value>
            MinLimit: 10
            MaxLimit: 10
            InitialLimit: 10
            ValidateConnection: true
        </value>
    </property>
</bean>

<bean id="dao" class="test.DAO">
    <property name="dataSource" ref="dataSource"/>
</bean>

0 个答案:

没有答案