数据库连接方式改进

来源:互联网 发布:mac粉 编辑:程序博客网 时间:2024/05/22 12:02

描述:

现有的数据库连接方式是每次调用MySQL.getConnection均会从连接池获取一个真实的连接,如下图所示。



此种数据库连接方式,假设action中使用循环调用service的方法,或者同一个action的种方法中调用了多个service, 则每个service中的connection均是从连接池获取的连接,如此种方式消耗的数据库连接太多,很容易爆满。上面的链接方式是//方式一


方式二

在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程, 从action中调用下面的service均是顺序调用的,即不会存在并发访问,一个sesion请求,web服务器会开启一个线程进行处理,即从拦截器开始可以认为是单线程下运行的,这样来看实际只需要一个数据库连接即可。

使用线程局部变量在保存首次获取的连接,在下次请求是再此返回同一个连接,直到方法执行完毕在释放次连接,看下面的应用本地线程变量写的程序

public class ConnectionManager{    private static Log log = LogFactory.getLog(ConnectionManager.class);private static final ThreadLocal threadConection = new ThreadLocal();    public static Connection getConnection() throws SQLException {//方式二/** * 优点: 基于线程sesion管理连接,同一个线程由于是顺序操作,只用一个数据库连接即可,无需手动关闭,可统一关闭连接,大大降低数据库连接池资源的消耗,增加数据库并发连接 * 缺点: 对于service调用service的代码部分,如果子service关闭了连接,主service方法需要再次获取连接,对现有代码需要改动 * 弥补: 自定义一个Connection的实现,拦截close方法,统一使用拦截器自动管理连接 */Connection conn = (Connection) threadConection.get();try {if (conn == null || conn.isClosed()) {conn = dataSources.getConnection();conn.setAutoCommit(false);if (conn != null) {connectionCountOpened++;threadConection.set(conn);}}} catch (Exception e) {e.printStackTrace();}getConectionString();return conn;        }    public static void closeConection(){        Connection conn = (Connection)threadConection.get();        try {            if (conn != null && !conn.isClosed()) {                conn.close();                log.info(Thread.currentThread()+"  close database connection.");            }        }catch(Exception e){            e.printStackTrace();            log.error(e);        }    }}

在给出service方法的拦截器,在service的方法执行完毕后再关闭连接

public class ServiceMethodInterceptor implements MethodInterceptor {    private static Log log = LogFactory.getLog(ServiceMethodInterceptor.class);    @Override    public Object invoke(MethodInvocation invocation) throws Throwable {        String info = invocation.getMethod().getDeclaringClass()+ "." +  invocation.getMethod().getName() + "()";        Object[] ars = invocation.getArguments();        log.warn("service method "+invocation.getMethod()+"");        // 判断该方法是否加了@LoginRequired 注解//        if(invocation.getMethod().isAnnotationPresent(LoginRequired.class)){//            System.out.println("----------this method is added @LoginRequired-------------------------");//        }        try{            Object result = invocation.proceed();            ConnectionManager.closeConection();            return result;        }catch(Exception e){            e.printStackTrace();            log.error(e);        }finally{            log.info(info);        }        return null;    }}
  * 优点: 基于线程sesion管理连接,同一个线程由于是顺序操作,只用一个数据库连接即可,无需手动关闭,可统一关闭连接,大大降低数据库连接池资源的消耗,增加数据库并发连接
 * 缺点: 对于service调用service的此种结构部分,如果子service关闭了连接,主service方法需要再次获取连接,对现有代码需要改动
 * 改进: 自定义一个Connection的实现,拦截close方法,统一使用拦截器自动管理连接


本文原址: 

0 0
原创粉丝点击