2

我在使用 Spring JDBC + Oracle 10g 时遇到了一个奇怪的问题。这是我的数据源配置:

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE" /> 
        <property name="username" value="admin" />
        <property name="password" value="admin" />
        <property name="validationQuery" value="SELECT 1 FROM DUAL"/>
        <property name="testOnBorrow" value="true"/>
        <property name="connectionProperties" value="defaultRowPrefetch=1000" />
    </bean>

起初,我认为正在设置 connectionProperties 值,但当我在 SQL Developer 中微调查询时(成本从 3670 变为 285,计划解释从:45 变为:03),应用程序中的时间从未从原来的15秒。删除 connectionProperties 设置无效。所以,我所做的是:

DAO 类

private List<Activity> getAllActivitiesJustJDBC() {
    String query = "select * " + "from activity a, work_order w "
            + "where a.ac_customer = 'CSC' "
            + "and w.wo_customer = a.ac_customer "
            + "and a.ac_workorder = w.wo_workorder ";
    long startTime = System.currentTimeMillis();
    List<Activity> activities = new ArrayList<Activity>();
    try {
        Connection conn = jdbcTemplate.getDataSource().getConnection();
        PreparedStatement st = conn.prepareStatement(query);
        st.setFetchSize(1000);
        ResultSet rs = st.executeQuery();
        ActivityMapper mapper = new ActivityMapper();
        while (rs.next()) {
            Activity activity = mapper.mapRow(rs, 1);
            activities.add(activity);
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    System.out.println("Time it took...."
            + (System.currentTimeMillis() - startTime));
    System.out.println("Number of activities = " + activities.size());
    return activities;
} 

这一次,获取 11,115 行所需的时间平均为 2 秒。关键语句是 setFetchSize(1000)。所以....我喜欢选项#2,但我需要关闭连接还是 Spring 为我处理这个?在选项 #1 中,我将使用 jdbcTemplate 调用查询方法,使用我的数据对象传入参数化查询和 BeanPropertyRowMapper 实例,然后返回列表。

4

1 回答 1

0

Ok from looking at other questions similar to this one, I do need to close out the connection starting with the result set, then statement, and then the connection using a finally. I also remembered (from the days before Spring) I needed to wrap all that around a try/catch and then not really do anything if an exception occurs closing a connection.

FYI, I wonder if there's a way to set the fetch size when defining the datasource using Spring.

Here's the final method:

private List<Activity> getAllActivitiesJustJDBC() {
    String query = "select * " + "from activity a, work_order w "
            + "where a.ac_customer = 'CSC' "
            + "and w.wo_customer = a.ac_customer "
            + "and a.ac_workorder = w.wo_workorder ";
    long startTime = System.currentTimeMillis();
    List<Activity> activities = new ArrayList<Activity>();
    Connection conn = null;
    PreparedStatement st = null;
    ResultSet rs = null;
    try {
        conn = jdbcTemplate.getDataSource().getConnection();
        st = conn.prepareStatement(query);
        st.setFetchSize(1000);
        rs = st.executeQuery();
        while (rs.next()) {
            activities.add(ActivityMapper.mapRow(rs));
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    finally {
        try {
            rs.close();
            st.close();
            conn.close();
        }
        catch (Exception ex){
            //Not much we can do here
        }
    }
    System.out.println("Time it took...."
            + (System.currentTimeMillis() - startTime));
    System.out.println("Number of activities = " + activities.size());
    return activities;
}
于 2012-08-16T13:54:10.483 回答