我对数据库交易有疑问,我不确定我的理解是否正确。我想在java应用程序中实现用户登录。由于可能有多个服务器作用于同一个数据库,并且每个用户只能登录其中一个服务器,因此如果用户已经登录,则数据库必须存储标志。
假设有以下表结构:
ID | User | PWD | Server
其中Server
是用户登录到的服务器的引用,如果他没有登录则为NULL
。
当用户登录时,我必须首先检查服务器值是否为NULL,如果不是,则将其设置为Corresponig参考值。但是,当这两个语句之间用户登录另一台服务器时会发生什么?交易可以检测到这种情况吗?例如(伪)
conn.setAutoCommit(false);
ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM users WHERE user = 'usr' AND password = 'pwd'");
if (rs.next()) {
rs.getInt("Server");
if (rs.wasNull()) {
// Not logged in
conn.createStatement().execute("UPDATE users SET server = 123 WHERE user = 'usr' AND password = 'pwd'");
conn.commit();
}
} else {
// Usr/Pwd wrong
}
conn.rollback();
如果用户在另一台服务器上的select和update语句之间登录,会发生什么?提交失败,因为在交易过程中表被其他人更改了,或者它是否仍在执行?
我应该更好地使用像
这样的方法UPDATE users SET server = 123 WHERE user = 'usr' AND pwd = 'pwd' AND server IS NULL
并检查0行是否受到影响?如果是这样,我必须检查用户是否存在于查询中。
使用INSERT注册新用户时会出现Simmilar问题。 Shoud我使用事务方法,或者将用户列声明为UNIQUE并捕获SQL异常?
答案 0 :(得分:2)
使用您对伪代码建议的事务将解决此问题,但请确保将事务隔离级别设置为TRANSACTION_REPEATABLE_READ。有关详细信息,请参阅此tutorial。
你还需要思考:
答案 1 :(得分:0)
在更新用户行的情况下,您可以指定锁定该特定行,以便其他任何jdbc连接都不能修改它。