gpt4 book ai didi

java - 来自jndi数据源/连接池的jdbc连接的“延迟初始化”:可行性

转载 作者:行者123 更新时间:2023-11-30 09:38:10 26 4
gpt4 key购买 nike

我有一个主控制器servlet,在其中实例化了一个数据源。 servlet打开和关闭连接。 servlet主要使用“工厂模式”实例化来自应用程序的命令。这是一些代码来解释:

public void init() throws ServletException {
super.init();
try {
datasource =(DataSource) getServletContext().getAttribute("DBCPool");
}
catch (Exception e) {

}
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//some code...
Connection connection = null;
if(cmd.mightNeedLazyLoadingAConnection)
{

connection = null;
}
else
connection = getConnection();//where getConnection is a method: datasource.getconnection();

//now a command (a java class) is instantied, to which the "null" CONNECTION obj is passed as parameter
cmdFactory.getInstance().getCommand(Cmd).execute(tsk,connection);


//some code

//Then wherever there is catch exception i close() the connection
// and it is always closed in finally
finally {
if(connection!=null)
connection.close()
}

}


现在,这对于第一种情况有一个问题,即connection = null,因为它永远不会在“ finally”部分中关闭连接(在下面的Update中解释了为什么)。

“ connection = null”用于命令可能不需要打开数据库连接的情况,因为它正在寻找的数据被缓存在 identity map中。


我试图在.execute(tsk,connection);中将“ Connection” obj作为“ null”参数传递;然后在相应的Java类中根据需要打开连接

->它确实在命令内打开了连接,但是当过程返回到servlet时:“ Connection”为空,因此未关闭。
我该怎么做才能使“ Connection” obj的值得到更新,以便当返回servlet时不再为“ Null”,并且我能够将其关闭?

我通常更喜欢使用打开/关闭数据库连接的控制器servlet,因此处理这种情况的最佳方法是什么,即您必须从池中同时“某种方式”从数据库中“延迟加载”数据库连接。时间保持分配给servlet的数据库连接的打开/关闭?


更新(进一步解释):


说我有一个命令:X.java
该命令可能/可能不需要数据库连接(取决于搜索的数据是否在身份映射中)


我想拥有的系统是:

(1)“客户请求”

(2)--->“ Servlet”:command.execute(connection)//,其中connection = null

(3)--->“命令X”:我是否需要进入数据库或记录在身份映射中?
(3.a)需要进入数据库的情况:
(3.a.1)连接= datasource.getconnection
(3.a.2)去获取数据

(4)--->返回servlet:关闭“ Servlet”中的“连接”

现在它一直工作到(3.a.2),但是一旦回到(4),连接似乎仍然是“空”,因此代码如下:

finally { 
if(connection!=null)
connection.close()
}


不起作用(不关闭连接),因此数据库池就这样耗尽了。
如何以“ null”开头并在命令“ X”中更改的连接如何将“ globaly”更新为其新值,而不仅是在命令“ X”的范围内“更新”?

解决方案

如果遇到相同的情况,可以选择以下两种解决方案:


您可以使用 LazyConnectionDataSourceProxy,如@Ryan Stewart提到的那样,它可以提供“简洁的抽象”和更专业的解决方案
或者,如果您想使用下面描述的解决方案(基本上,我实现了一个类似于“ LazyConnectionDataSourceProxy”的类,但它不太干净,它的细节抽象程度低于“ LazyConnectionDataSourceProxy”))


我的个人解决方案,详细信息:



我创建了一个“ Helper”类,该构造函数将“ datasource”作为参数
此类帮助器类具有以下方法:从池“延迟获取”连接,“关闭”连接
此类在Servlet中实例化,并且仅在整个应用程序中需要时,才从池中获取连接。


这是我在servlet中添加/修改的代码:

Connection connection = null;
if(cmd.mightNeedLazyLoadingAConnection)
{

helper hp = new helper(datasource);
cmdFactory.getInstance().getCommand(Cmd).execute(tsk,hp);
}
else
{
connection = getConnection();
cmdFactory.getInstance().getCommand(Cmd).execute(tsk,connection);
}


然后在命令“ X”中说,我需要一个数据库连接:

Connection connection = hp.LazyGet();//Now got a connection from the pool


这样,当流程回到Servlet级别时,我可以:



回滚
承诺
等等..


关于帮助程序类的此hp对象。

我从中得到什么好处:


我将所有数据库的打开/关闭/提交/回滚限制在一个地方,即Servlet,它负责执行命令。
有3种情况:永远不需要db /永远需要db /可能需要db,因此现在我将对数据库的调用减少了1/3,这知道很多数据库功能随着新功能和新用户注册而呈指数增长,这是很多的。


这可能不是最干净的解决方法,但是在这种方式与进行额外的“不必要的” 1/3数据库调用之间,它肯定会更好。或者,如果您想使用经过测试,抽象和简洁的方法,则只需使用 LazyConnectionDataSourceProxy

最佳答案

使用LazyConnectionDataSourceProxy。然后每次都获得一个“连接”,但是只有当您实际执行需要连接的操作时,才会打开真正的连接。因此,您会遵守Hiro2k指出的“创建/销毁”知识,因为连接的生命周期完全由servlet管理。

关于java - 来自jndi数据源/连接池的jdbc连接的“延迟初始化”:可行性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10240397/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com