当前位置:  开发笔记 > 编程语言 > 正文

Java Web应用程序数据访问类中的线程安全性

如何解决《JavaWeb应用程序数据访问类中的线程安全性》经验,为你挑选了1个好方法。

我的业余爱好项目是Java Web应用程序.这是一个带有表单的简单网页.用户填写表单,提交并显示一些结果.

数据来自JDBC连接.当用户提交时,我验证输入,构建"CREATE ALIAS"语句,"SELECT"语句和"DROP ALIAS"语句.我执行它们并从查询中执行我需要对ResultSet执行的任何操作.

由于我正在使用的特定数据库/ JDBC组合上的ALIASes存在问题,因此每次运行查询时都需要使用唯一名称创建这些ALIAS.我正在使用int来确保每次进入数据库时​​都会增加.

所以,我的数据访问类看起来有点像:

private final static Connection connection = // initialized however

private static int uniqueInvocationNumber = 0;

public static Whatever getData(ValidatedQuery validatedQuery) {
    String aliasName = "TEMPALIAS" + String.valueOf(uniqueInvocationNumber);
    // build statements, execute statements, deal with results
    uniqueInvocationNumber++;
}

这有效.然而,我最近意识到我坚定地坚持使用Jon Skeet的线程知识第0阶段("完全无知 - 忽略任何问题的可能性.") - 我从未编写过线程代码或线程感知代码.我完全不知道当许多用户同时使用该应用程序时会发生什么.

所以我的问题是,(假设我没有通过盲目的运气/ J2EE魔术偶然发现线程安全):

我怎样才能保证这个安全?

我在这里列出了我认为相关的信息,但如果这还不够,请告诉我.

太感谢了.

编辑:这是一个使用Wicket框架的合适的J2EE Web应用程序.我通常在Jetty中部署它.

编辑:关于ALIASes动机的长篇故事,对于那些感兴趣的人:

有问题的数据库是AS400上的DB2(i5,System i,iSeries,这些天IBM正在调用它),我正在使用jt400.

虽然AS400上的DB2有点像任何其他平台上的DB2,但由于遗留的东西,表有一个"成员"的概念.一个成员有点像桌子的一大块.我想要运行的查询是

SELECT thisField FROM thisTable(thisMember)

它将thisMember视为一个表,因此只需为成员中的所有行提供thisField.

现在,像这样的查询在交互式SQL会话中运行良好,但不能通过JDBC工作(我不知道为什么).我使用的解决方法是做类似的事情

CREATE ALIAS tempAlias FOR thisTable(thisMember)

那么一个

SELECT thisField FROM tempAlias

那么一个

DROP ALIAS tempAlias

但是对于一个停止显示的问题有效:当你使用ALIAS重复执行此操作时总是称为"tempAlias",并且有一个thisField从一个查询到下一个查询的长度不同的情况,结果集会在第二次查询时出现乱码查询(第一行的getString很好,下一个有前面有一定数量的空格,下一个空格的前面有相同数量的空格 - 这是来自内存,但它就是这样的).

因此,确保每个ALIAS都有一个明确的名称可以解决这个问题.

我刚刚意识到(花了很多时间来解释这个解释)我可能在抓住解决方法之前没有花足够的时间思考这个问题.不幸的是,我还没有实现为我的卧室购买AS400的梦想;)所以我现在不能尝试任何新的东西.



1> Jon Skeet..:

好吧,我暂时忽略任何SQL内容,只关注uniqueInvocationNumber部分.这里有两个问题:

无法保证线程在任何特定点都能看到最新值

增量不是原子的

在Java中解决此问题的最简单方法是使用AtomicInteger:

private static final AtomicInteger uniqueInvocationNumber = new AtomicInteger();

public static Whatever getData(ValidatedQuery validatedQuery) {
    String aliasName = "TEMPALIAS" + uniqueInvocationNumber.getAndIncrement()
    // build statements, execute statements, deal with results
}

请注意,这仍然假设您只在单个服务器上运行单个实例.对于一个可能是合理假设的家庭项目:)

另一个潜在的问题是在不同线程之间共享单个连接.通常,处理数据库连接的更好方法是使用连接池,并在需要的地方"打开/使用/关闭"连接(关闭finally块中的连接).

推荐阅读
爱唱歌的郭少文_
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有