数据库重新启动后Jboss数据源恢复

时间:2010-01-23 00:07:49

标签: java jboss datasource

仍然在连接池中的已关闭连接 - 为什么?

的servlet -

public class Index extends HttpServlet {

    TimeZoneService timeZoneService;

    public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException {
        WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
        timeZoneService = (TimeZoneService) ctx.getBean("timeZoneService");
        timeZoneService.loadAllTimeZones();
        System.out.println("Done");
    }
}

public interface TimeZoneService {
    void loadAllTimeZones();
}

public class TimeZoneServiceImpl implements TimeZoneService {

    private TimeZoneDao tzDao;
    private Map<Long, String> tzOid2JavaName = new HashMap<Long, String>();

    public void loadAllTimeZones() {
        List<TimeZone> timeZones = tzDao.findAllTimeZones();
        for (TimeZone tz : timeZones) {
            tzOid2JavaName.put(tz.getOid(), tz.getJavaName());
        }
    }

    public void setTzDao(TimeZoneDao tzDao) {
        this.tzDao = tzDao;
    }
}

public interface TimeZoneDao {
    List<TimeZone> findAllTimeZones() throws DataAccessException;  
}

public class TimeZoneDaoImpl extends JdbcDaoSupport implements TimeZoneDao {

    public List<TimeZone> findAllTimeZones() throws DataAccessException
    {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT TZ.OID, TZ.JAVA_NAME FROM TIME_ZONE TZ");
        List<TimeZone> timeZones = getJdbcTemplate().query(sql.toString(), new RowMapper() {
            public Object mapRow(ResultSet rs, int i) throws SQLException {
                TimeZone tz = new TimeZone();
                tz.setOid(rs.getLong("OID"));
                tz.setJavaName(rs.getString("JAVA_NAME"));
                return tz;
            }
        });

        return timeZones;
    }
}

public class TimeZone {
    private Long oid;
    private String javaName;

    public Long getOid() {
        return this.oid;
    }

    public void setOid(Long oid) {
        this.oid = oid;
    }

    public String getJavaName() {
        return this.javaName;
    }

    public void setJavaName(String javaName) {
        this.javaName = javaName;
    }
}

弹簧-config.xml中

<beans>

    <jee:jndi-lookup id="dataSource" jndi-name="java:/OracleDS"/>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="timeZoneDao" class="dao.impl.TimeZoneDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="timeZoneService" class="logic.impl.TimeZoneServiceImpl">
        <property name="tzDao" ref="timeZoneDao"/>
    </bean>

</beans>

的web.xml

<web-app>

    <display-name>Spring</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            WEB-INF/spring-config.xml,classpath*:/META-INF/spring-config.xml</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>index</servlet-name>
        <display-name>Index page</display-name>
        <description>Landing page</description>
        <servlet-class>servlet.Index</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>index</servlet-name>
        <url-pattern>/index</url-pattern>
    </servlet-mapping>

    <!-- Session Timeout (in minutes) -->
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
</web-app>

的MySQL-ds.xml中

<datasources> 
   <local-tx-datasource> 
      <jndi-name>OracleDS</jndi-name> 
      <connection-url>jdbc:mysql://localhost:3306/spring</connection-url> 
      <driver-class>com.mysql.jdbc.Driver</driver-class> 
      <user-name>spring_test</user-name> 
      <password>spring_test13</password> 
      <min-pool-size>1</min-pool-size> 
      <max-pool-size>5</max-pool-size> 
      <idle-timeout-minutes>2</idle-timeout-minutes> 
   </local-tx-datasource> 
</datasources>

3 个答案:

答案 0 :(得分:7)

确定。希望以下内容对某人有用: - )

有一个数据源配置设置 - exception-sorter-class-name

根据Jboss,这用于a class that looks at vendor specific messages to determine whether sql errors are fatal and thus the connection should be destroyed. If none specified, no errors will be treated as fatal.

如果使用Oracle数据库,则此配置设置为org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter。该类具有需要被视为致命的所有错误代码,因此需要销毁连接。

在Jboss 4中,错误代码17002(连接重置)&amp;&amp; 17008(连接已关闭)不包括在内。它们是在Jboss 5中添加的。因此,如果您正在使用Jboss 4并想知道为什么没有恢复连接,请尝试添加丢失的代码。

答案 1 :(得分:2)

这是使用连接池时遇到的常见问题。当应用程序从池中借用连接时,池本身应该“测试”连接,确保它仍然有效,还是应该将其留给应用程序?

如果池测试连接,这不可避免地涉及向数据库服务器发送连接(通常是某种类型的基本SELECT)。在高流量系统上,这非常浪费,并且会给数据库服务器带来相当大的压力。

但是,在低流量站点上,您的数据库可以处理额外负载,您可以配置数据源以使JBoss在将连接传递给应用程序之前验证连接。如果连接已经死亡,JBoss会将它从池中删除并获得一个新的连接,以便在数据库重启后继续存在。

任何,请将其添加到您的mysql-ds.xml文件中:

<check-valid-connection-sql>select 1 from mytable</check-valid-connection-sql>

您必须自己选择查询,确保它不是一个昂贵的查询,因为它将运行批次

请参阅JBoss documentation wiki以了解如何修改这些数据源文件。

答案 2 :(得分:2)

以下是oracle DB对 jboss 7.1 + 的连接验证配置:

<validation>
   <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.vendor.OracleValidConnectionChecker"/>
   <check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>
   <stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.vendor.OracleStaleConnectionChecker"/>
   <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter"/>
</validation>

现在Jboss将验证您的每一个连接。