在多线程系统中使用静态java.sql.Connection实例安全吗?

在多线程系统中使用静态java.sql.Connection实例安全吗?,java,multithreading,servlets,jdbc,connection,Java,Multithreading,Servlets,Jdbc,Connection,我正在Tomcat上运行一个web应用程序。我有一个处理所有DB查询的类。 此类包含连接对象和返回查询结果的方法 这是连接对象: private static Connection conn = null; 它只有一个实例singleton 此外,我还有执行查询的方法,例如在数据库中搜索用户: public static ResultSet searchUser(String user, String pass) throws SQLException 此方法使用静态连接对象。我的问题是,我

我正在Tomcat上运行一个web应用程序。我有一个处理所有DB查询的类。 此类包含连接对象和返回查询结果的方法

这是连接对象:

private static Connection conn = null;
它只有一个实例singleton

此外,我还有执行查询的方法,例如在数据库中搜索用户:

public static ResultSet searchUser(String user, String pass) throws SQLException
此方法使用静态连接对象。我的问题是,我在静态连接对象中的使用是线程安全的吗?或者,当许多用户调用searchUser方法时,它会导致问题吗?

如果您只运行选择查询searchUser听起来像是只选择数据,除了线程争用之外,不会有任何问题

据我所知,一个连接一次只能处理一个查询,所以通过使用单个实例,基本上可以序列化数据库访问。但这并不一定意味着,在多线程环境中访问这样的数据库总是安全的。如果并发访问是交错的,则可能仍然存在问题

我在静态连接对象中的使用是线程安全的吗

绝对不是! 这样,连接将在所有用户发送的所有请求之间共享,因此所有查询将相互干扰。但是线程安全不是你唯一的问题,资源泄漏也是你的另一个问题。在应用程序的整个生命周期中,您保持一个连接处于打开状态。只要连接打开的时间过长(通常在30分钟到8小时之间),一般数据库都会回收连接,具体取决于数据库的配置。因此,如果您的web应用程序运行的时间超过此时间,则连接将丢失,您将无法再执行查询

当这些资源作为类实例的非静态实例变量持有时,这个问题也适用,该类实例被多次重用

您应该始终在尽可能短的范围内获取并关闭连接、语句和结果集,最好是在与您根据以下JDBC习惯用法执行查询的位置相同的范围内:

公共用户查找字符串用户名,字符串密码引发SQLException{ User=null; 尝试 Connection=dataSource.getConnection; PreparedStatement语句=connection.PrepareStatement选择id、用户名、来自用户名为?且密码为md5的用户的电子邮件; { statement.setString,用户名; statement.setString2,密码; try ResultSet ResultSet=statement.executeQuery{ 如果resultSet.next{ 用户=新用户; user.setIdresultSet.getLongid; user.setUsernameresultSet.getStringusername; user.setEmailresultSet.getStringemail; } } } 返回用户; } 请注意,不应在此处返回结果集。您应该立即读取它,并将其映射到非JDBC类,然后返回它,以便可以安全地关闭ResultSet

如果您还没有使用Java7,那么请使用try finally块,在该块中,您可以在获取可关闭资源时按相反顺序手动关闭这些资源。您可以在此处找到一个示例:

如果您担心连接性能,那么应该改用连接池。这是许多JavaEE应用服务器中内置的,甚至像Tomcat这样的基本servletcontainers也支持它。只需在服务器本身中创建一个JNDI数据源,并让您的webapp将其作为数据源抓取即可。它显然已经是一个连接池。您可以在下面列表的第一个链接中找到一个示例

另见:
虽然这与当前的问题无关,但出于好奇,hibernate也做了同样的事情。我的意思是,每次我们创建会话对象时,它是否会创建新的连接对象并在使用后关闭。@Vikas:Hibernate没有那么愚蠢:是的,它正确地完成了。作为开发人员,您仍然需要确保正确使用Hibernate会话,即不要将其指定为静态变量或其他内容。@BaluC:如果我们使用类似于此web链接中的代码,该怎么办?它使用的是C3P0-@JustCause:Explore,请参见答案底部的链接。请注意,您的链接不使用静态连接,这里的问题就是所有这些。@BalusC:我知道,我只是想知道该代码对web是否更安全。有什么想法吗?