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

Java 数据库重新启动后恢复Jboss数据源,java,jboss,datasource,Java,Jboss,Datasource,已关闭的连接仍在连接池中-为什么 servlet- public class Index extends HttpServlet { TimeZoneService timeZoneService; public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException { WebApplicationContext ctx = WebApplicat

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

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;
    }
}
公共类索引扩展了HttpServlet{
时区服务时区服务;
public void doGet(HttpServletRequest-req,HttpServletResponse-res)抛出ServletException{
WebApplicationContext ctx=WebApplicationContextils.getRequiredWebApplicationContext(getServletContext());
timeZoneService=(timeZoneService)ctx.getBean(“timeZoneService”);
timeZoneService.loadAllTimeZones();
系统输出打印项次(“完成”);
}
}
公共接口时区服务{
void loadAllTimeZones();
}
公共类TimeZoneServiceImpl实现TimeZoneService{
私人时区dao tzDao;
私有映射tzOid2JavaName=newHashMap();
public void loadAllTimeZones(){
List timeZones=tzDao.findAllTimeZones();
用于(时区tz:时区){
tzOid2JavaName.put(tz.getOid(),tz.getJavaName());
}
}
公共无效setTzDao(时区dao tzDao){
this.tzDao=tzDao;
}
}
公共接口时区{
List findAllTimeZones()抛出DataAccessException;
}
公共类TimeZoneDaoImpl扩展JDBCDAO支持实现TimeZoneDao{
公共列表findAllTimeZones()引发DataAccessException
{
StringBuffer sql=新的StringBuffer();
append(“从时区TZ中选择TZ.OID、TZ.JAVA_名称”);
List timeZones=getJdbcTemplate().query(sql.toString(),new RowMapper()){
公共对象映射行(ResultSet rs,int i)引发SQLException{
时区tz=新时区();
z.setOid(rs.getLong(“OID”);
setJavaName(rs.getString(“JAVA_NAME”));
返回tz;
}
});
返回时区;
}
}
公共类时区{
私人长骨;
私有字符串javaName;
公共长getOid(){
返回此.oid;
}
公共void setOid(长oid){
this.oid=oid;
}
公共字符串getJavaName(){
返回this.javaName;
}
public void setJavaName(字符串javaName){
this.javaName=javaName;
}
}
spring-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>

春天
上下文配置位置
WEB-INF/spring-config.xml,classpath*:/META-INF/spring-config.xml
org.springframework.web.context.ContextLoaderListener
指数
索引页
登录页
servlet.Index
指数
/索引
60
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>

神谕
jdbc:mysql://localhost:3306/spring 
com.mysql.jdbc.Driver
弹簧试验
春季考试13
1.
5.
2.

这是使用连接池时常见的问题。当应用程序从池借用连接时,池本身是否应该“测试”连接以确保其仍然有效,还是应该让应用程序自行决定

如果池测试连接,这不可避免地涉及到将连接中的某些内容发送到数据库服务器(通常是某种基本选择)。在高流量系统上,这是非常浪费的,并且会给数据库服务器增加相当大的压力

不过,在低流量站点上,您的数据库可以处理额外的负载,您可以配置数据源,使JBoss在将连接传递给应用程序之前验证连接。如果连接已断开,JBoss将从池中删除它并获得一个新的连接,以便在数据库重新启动后仍能生存

如果有,请将此添加到您的
mysql ds.xml
文件中:

<check-valid-connection-sql>select 1 from mytable</check-valid-connection-sql>
从mytable中选择1
您必须自己选择查询,确保它不是一个昂贵的查询,因为它会运行很多次


请参阅以查看如何修改这些数据源文件。

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

有一个数据源配置设置-
异常分类器类名

根据Jboss的说法,这用于
一个类,该类查看特定于供应商的消息,以确定sql错误是否是致命的,因此应该销毁连接。如果未指定任何错误,则不会将任何错误视为致命错误。

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


在JBoss4中,错误代码17002(连接重置)和17008(连接关闭)不包括在内。它们被添加到JBoss5中。因此,如果您正在使用Jboss 4,并且想知道为什么没有恢复连接,请尝试添加缺少的代码。

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


从双重选择中选择1

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

mysql-ds.xml OracleDS jdbc:mysql://localhost:3306/spring com.mysql.jdbc.Driver spring\u test spring\u test13 1 5 2是。还有另外一个配置,可以看到Jboss在返回连接之前做了一些事情。有效的连接检查器类名应该比发出SQL的类名“更好”。既然您提到应用程序应该能够处理这种情况,我想知道Hibernate/Spring框架是否能为我们做到这一点?因为所有数据库的标准代码都会出现关闭连接异常。不,Spring和Hibernate都不能更好地处理这个问题。如果要重新启动数据库服务器,请使用连接检查器,或者重新启动appserver。哦,而且
有效的连接检查器类名
也会发出SQL,它只是在幕后进行。这是不可能的
<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>