Jooq,Spring和BoneCP连接关闭了两次错误

时间:2014-01-28 01:49:07

标签: spring connection jooq bonecp

我正在使用Spring 4.0.0,以及jOOQ 3.2.0和BoneCP 0.8.0用于Web应用程序。

我将PersistenceContext的配置与本指南相同(请略读一下这里要粘贴的代码太多了)

http://www.petrikainulainen.net/programming/jooq/using-jooq-with-spring-configuration/

但最大连接数较少,而closeConnectionWatch = true则表示错误检查。

从我可以推断,本指南是jOOQ网站自己的指南的非XML版本

http://www.jooq.org/doc/3.2/manual/getting-started/tutorials/jooq-with-spring/

我的问题可能来自于可能不知道如何使用jOOQ生成的DAO或@Transactional注释。我遇到了“连接关闭两次”异常的负载,这使我的应用程序从根本上被打破。下面的堆栈跟踪实际上并没有说它关闭了两次,但是closeConnectionWatch的输出说明了

的内容。
bonecp connection closed twice detected: first location connection was closed in thread[blah]
closed again in thread[blah2]

连接监视完成后,SQL异常的堆栈跟踪:

Jan 28, 2014 10:51:51 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/application] threw     exception [Request processing failed; nested exception is org.springframework.jdbc.UncategorizedSQLException: jOOQ; uncategorized SQLException for SQL 
<snip> error code [0]; Connection is closed!; nested exception is java.sql.SQLException: Connection is closed!] with root cause java.sql.SQLException: Connection is closed!
at com.jolbox.bonecp.ConnectionHandle.checkClosed(ConnectionHandle.java:459)
at com.jolbox.bonecp.ConnectionHandle.prepareStatement(ConnectionHandle.java:1011)
at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.invoke(LazyConnectionDataSourceProxy.java:376)
at com.sun.proxy.$Proxy73.prepareStatement(Unknown Source)
at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy$TransactionAwareInvocationHandler.invoke(TransactionAwareDataSourceProxy.java:240)
at com.sun.proxy.$Proxy73.prepareStatement(Unknown Source)
at org.jooq.impl.ProviderEnabledConnection.prepareStatement(ProviderEnabledConnection.java:112)
at org.jooq.impl.SettingsEnabledConnection.prepareStatement(SettingsEnabledConnection.java:76)
at org.jooq.impl.AbstractResultQuery.prepare(AbstractResultQuery.java:224)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:295)
at org.jooq.impl.AbstractResultQuery.fetch(AbstractResultQuery.java:324)
at org.jooq.impl.SelectImpl.fetch(SelectImpl.java:1034)
at org.jooq.impl.DAOImpl.fetch(DAOImpl.java:249)
----> at com.myapplication.spring.services.UserService.authenticate(UserService.java:32)
at com.myapplication.spring.controllers.LoginController.doLogin(LoginController.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:214)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:748)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.github.dandelion.datatables.core.web.filter.DatatablesFilter.doFilter(DatatablesFilter.java:73)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:931)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

我所指向的行是服务中用于调用数据库的行。我在服务中有@Autowired DAO对象,如下所示

@Service("UserService")
public class UserService implements UserServiceInterface{

@Autowired UsersDao userDao;
@Autowired PasswordServiceInterface passwordService;

@Override

public Users authenticate(String user,String password) {
    boolean allowedIn = false;

    List<Users> users = userDao.fetch(USERS.USERNAME, user);
            //do something here

我在类似服务中使用的其他函数包含使用DSLContext对象的调用,如

DSL.select(SOMETHING).from(SOMETABLE).fetch()

DAO和DSLContext在PersistenceContext中存储为bean,就像这样。 我作为DSLContext而不是* Default * DSLContext自动装配,因为jOOQ指南在底部有一个测试方法,只显示DSLContext。

@Bean
public DefaultDSLContext dsl() {
    return new DefaultDSLContext(configuration());
}

@Bean 
public UsersDao userDao() { //bad because UsersDao isn't an interface???
    return new UsersDao(configuration());
}   

这是控制器

@Controller
public class LoginController {

@Autowired UserServiceInterface userService;

@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login() {
    return "login";
}

@RequestMapping(value = "/login/doLogin", method = RequestMethod.POST)
public String doLogin(@RequestParam("username")String username, @RequestParam("password") String password, HttpSession session) {

    Users u = userService.authenticate(username, password);
    if(u == null) 
        return "redirect:/error";
    else {
        session.setAttribute("user", u.getUserid());
        session.setAttribute("role", u.getRoleid());
        session.setAttribute("retailgroup", u.getGroupid());
        return "redirect:/dashboard";
    }
}

UserService并不是我遇到错误的唯一服务 - 我的所有服务都相似,因为它们包含一个/两个DAO和一个DSLContext Autowired对象,使用与usersDao()相同的DAO配置构造函数,例如productsDao ()。 Products服务具有此DAO和DSLContext对象,与调用数据库的UsersService非常相似。

有时我会在登录时遇到此连接问题,有时候会很好,我可以浏览网站并查看产品一段时间,但随后我会得到一个“连接关闭!”来自另一个服务的错误(大约有5个以相同的方式写入)。

所以我的问题是

  1. 我在哪里使用@Transactional注释,它实际上做了什么。我对@Transactional注释的遗漏是否意味着我自己造成了问题?我之前已经在使用数据库的所有位置添加了它,但我无法确定它是否真的有用,因为我仍然遇到相同的错误。

  2. 这是我的范围问题吗?我知道bean默认为单例 - 我以这样的方式编写我的控制器,它们使用会话存储的属性传递给服务(它们都被保留为默认单例),因此它们可能只选择某个用户的数据被允许看到。

  3. 由于connectionPool正在关闭连接两次,这是否意味着问题是线程A和线程B同时进行连接,对它执行某些操作,然后两者都关闭?为什么会发生这种情况使用上述指南中的配置?如何确保线程安全或不是问题?

  4. DAO bean应该是接口吗?从我与Spring的简史相比,我被引导相信很多(很多/全部?)@Autowired bean应该是?我应该使用接口org.jooq.DAOImpl这是所有jOOQ生成的DAO似乎实现的接口吗?

    @Bean
    public org.jooq.impl.DAOImpl usersDao() {
        return new usersDao(configuration());
    }
    
  5. 对于长期问题道歉,任何帮助都将不胜感激。感谢。

    编辑:这是我在PersistenceContext类中的配置

    @Configuration
    @PropertySource("classpath:config.properties")
    public class PersistenceContext {
    
    @Autowired
    private Environment env;
    
    
    @Bean(destroyMethod = "close")
    public DataSource dataSource() {
        BoneCPDataSource dataSource = new BoneCPDataSource();
        dataSource.setDriverClass(env.getRequiredProperty("db.driver"));
        dataSource.setJdbcUrl(env.getRequiredProperty("db.url"));
        dataSource.setUsername(env.getRequiredProperty("db.username"));
        dataSource.setPassword(env.getRequiredProperty("db.password"));
        dataSource.setMaxConnectionsPerPartition(20);
        dataSource.setPartitionCount(2);
        dataSource.setCloseConnectionWatch(true);
        return dataSource;
    }
    
    @Bean
    public LazyConnectionDataSourceProxy lazyConnectionDataSource() {
        return new LazyConnectionDataSourceProxy(dataSource());
    }
    
    @Bean
    public TransactionAwareDataSourceProxy transactionAwareDataSource() {
        return new TransactionAwareDataSourceProxy(lazyConnectionDataSource());
    }
    
    @Bean
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(lazyConnectionDataSource());
    }
    
    @Bean
    public DataSourceConnectionProvider connectionProvider() {
        return new DataSourceConnectionProvider(transactionAwareDataSource());
    }
    
    @Bean
    public JOOQToSpringExceptionTransformer jooqToSpringExceptionTransformer() {
        return new JOOQToSpringExceptionTransformer();
    }
    
    @Bean
    public DefaultConfiguration configuration() {
        DefaultConfiguration jooqConfiguration = new DefaultConfiguration();
        jooqConfiguration.set(connectionProvider());
        jooqConfiguration.set(new DefaultExecuteListenerProvider(
            jooqToSpringExceptionTransformer()
        ));
    
        String sqlDialectName = env.getRequiredProperty("jooq.sql.dialect");
        SQLDialect dialect = SQLDialect.valueOf(sqlDialectName);
        jooqConfiguration.set(dialect);
    
        return jooqConfiguration;
    }
    
    @Bean
    public DefaultDSLContext dsl() {
        return new DefaultDSLContext(configuration());
    }
    
    @Bean
    public UsersDao userDao() {
        return new UsersDao(configuration());
    }
    
    }
    

1 个答案:

答案 0 :(得分:3)

在重新阅读您的问题和聊天后,我可以说这很可能是由于您使用的版本 3.2.0 ,这里有一个相当严重的错误:

该错误已在 3.2.2 中修复,您应升级(或稍后)。