使用带有Tomcat 7的CDI的ConnectionFactory的奇怪行为

时间:2015-11-06 02:40:11

标签: java tomcat cdi c3p0

我有这个类(我的数据库连接工厂):

@ApplicationScoped
public class ConnectionFactory {

    private ComboPooledDataSource datasource;

    private Long open = 0l;
    private Long close = 0l;

    @PostConstruct
    public void init() throws PropertyVetoException, SQLException {
        datasource = new ComboPooledDataSource();
        datasource.setDriverClass("org.postgresql.Driver");
        datasource.setJdbcUrl("jdbc:postgresql:dbcampanha");
        datasource.setUser("postgres");
        datasource.setPassword("admin");

        datasource.setMinPoolSize(1);
        datasource.setMaxPoolSize(5);

        datasource.setCheckoutTimeout(30000);
        datasource.setUnreturnedConnectionTimeout(30);
        datasource.setMaxIdleTime(30);

        datasource.setDebugUnreturnedConnectionStackTraces(true);

        datasource.setAcquireIncrement(1);
    }

    @Produces
    @RequestScoped
    public Connection getConnection() throws ClassNotFoundException {
        open++;

        try {
            Connection connection = datasource.getConnection();
            connection.setAutoCommit(false);

            return connection;
        } catch (SQLException e) {          
            throw new RuntimeException(e);
        }
    }

    public void close(@Disposes Connection connection) {
        close++;

        try {
            connection.commit();
            connection.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public Long getOpenedConnectionCounter() {
        return open;
    }

    public Long getClosedConnectionCounter(){
        return close;
    }

    public ComboPooledDataSource getDatasource(){
        return datasource;
    }

}

我将此类与JAX-RS应用程序一起使用。对于使用此路线的一些测试:

@RequestScoped
@Path("/test")
public class TesteService {

    @Inject
    private Connection connection;

    @GET
    @Produces(MyMediaType.JSON)
    @Path("/yes")
    public Response success() throws SQLException {
        connection.getClientInfo("");

        return Response.ok().build();
    }

}

我的客户的这个课程:

public class TesteMain {

    private static final String prefix = "http://localhost:8080/schoolwork/service/test/";

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 10000; i++) {
            Request request = new Request(prefix + "yes");
            request.start();

            if(i % 10 == 0)
                Thread.sleep(1000l);
        }
    }

    public static class Request extends Thread {

        private String rota;

        public Request(String rota){
            this.rota = rota;
        }

        @Override
        public void run() {
            try {
                HttpURLConnection url = (HttpURLConnection) (new URL(rota).openConnection());
                url.connect();

                System.out.println(url.getResponseCode() == 200 ? "SUCCESS" : "ERROR");
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

我收到此信息:

{
  "opened-connection": 789,
  "closed-connection": 867,
}

是的,我有一些关闭的数据库连接大于打开。怎么样?对此有何想法?

我使用

Tomcat 7 + Java 7

P.S。我很抱歉我的英文不好:/

解决

我更改了AtomicInteger对象的计数器,并且运行正常。

1 个答案:

答案 0 :(得分:1)

所以,两个快速评论:

  1. 你的计数器是(盒装的)长期读取和更新的1000个并发线程。他们的价值观通常是不可预测和不确定的。他们当然不会准确计算你打算算什么。考虑在AtomicLongs上使用原子操作。

  2. 您的commit()(或rollback())应附加到您的数据库业务逻辑中,您可以告诉工作单元成功或失败的部分。你不应该在关闭时自动提交。