gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 07:16:37 25 4
gpt4 key购买 nike

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

数据通过 JDBC 连接传入。当用户提交时,我验证输入,构建“CREATE ALIAS”语句、“SELECT”语句和“DROP ALIAS”语句。我执行它们并对查询中的 ResultSet 执行我需要执行的任何操作。

由于我正在使用的特定数据库/JDBC 组合上的 ALIAS 存在问题,因此每次运行查询时都需要使用唯一的名称创建这些 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 的 threading knowledge 的第 0 阶段。 (“完全无知 - 忽略任何可能出现问题的可能性。”) - 我从未编写过线程代码或线程感知代码。我完全不知道当许多用户同时使用该应用程序时会发生什么。

所以我的问题是,(假设我没有因运气/J2EE 魔法而偶然发现线程安全):

如何确保安全?

我在此处添加了我认为相关的信息,但如果还不够,请告诉我。

感谢一百万。

编辑:这是一个使用 Wicket 框架的正确 J2EE Web 应用程序。我通常将其部署在 Jetty 内。

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

有问题的数据库是 AS400 上的 DB2(i5、System i、iSeries,无论 IBM 现在如何调用它),我正在使用 jt400 .

虽然 AS400 上的 DB2 有点像任何其他平台上的 DB2,但由于遗留的东西,表有一个“成员”的概念。成员有点像表的一部分。我要运行的查询是

SELECT thisField FROM thisTable(thisMember)

它将 thisMember 本身视为一个表,因此只为您提供该成员中所有行的 thisField。

现在,诸如此类的查询在交互式 SQL session 中运行良好,但无法通过 JDBC 运行(我不知道为什么)。我使用的解决方法是执行类似的操作

CREATE ALIAS tempAlias FOR thisTable(thisMember)

然后

SELECT thisField FROM tempAlias

然后

DROP ALIAS tempAlias

这可以工作,但对于一个显示停止的问题:当您使用始终称为“tempAlias”的别名重复执行此操作时,并且有一种情况,其中 thisField 从一个查询到下一个查询的长度不同,结果集返回乱码对于第二个查询(第一行的 getString 没问题,下一个查询前面有一定数量的空格,下一个查询前面还有相同数量的空格 - 这是来自内存,但它是类似的东西)。

因此,解决方法是确保每个别名都有一个不同的名称,从而解决这个问题。

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

最佳答案

好吧,我暂时忽略任何 SQL 内容,只专注于 uniqueInitationNumber 部分。这里有两个问题:

  • 无法保证线程会在任何特定点看到最新值
  • 增量不是原子的

在 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 block 中关闭连接)。

关于java - Java Web 应用程序数据访问类中的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/573194/

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