我有一个简单的数据库表users
,包含3列:
| id | username | nationality |
| 1 | John | American |
| 2 | Doe | English |
我想通过POST
请求向http://mysite/users/2/nationality
现在我的初步方法是进行单一查询
UPDATE users SET nationality="French" WHERE id=2;
后跟查询更新后的对象SELECT * FROM users WHERE id=2;
,然后在响应中返回更新后的对象。
问题是我的数据库中可能不存在请求中传递的id
。 如何验证用户是否存在于数据库中?
UserNotFoundException
?public void updateRecord(Long id, String username) { String updateSql = "UPDATE users SET username = ? WHERE id = ?"; JdbcTemplate template = new JdbcTemplate(dataSource); Object[] params = { username, id}; int[] types = {Types.VARCHAR, Types.BIGINT}; int rows = template.update(updateSql, params, types); System.out.println(rows + " row(s) updated."); }
答案 0 :(得分:2)
如果您始终需要更新以在响应中返回更新的对象,则选项1似乎是检查更新是否与现有用户匹配的合理方法。虽然如果您没有使用交易,但您应该知道在更新时用户可能不存在,但是单独的连接可能会在您选择之前插入用户。
也就是说,没有事务,select总是有可能将对象返回到与刚执行的更新不同的状态。但是,在这种情况下,情况稍差,因为从技术上讲,更新应该失败。
如果您不需要更新来返回响应中的更新对象,那么选项2似乎是一个更好的解决方案。但是,要使其工作,您需要更新以返回匹配行的数量而不是更改行的数量(因此,如果更新与现有用户匹配,但您正在更新的字段不会更改,您和# 39; ll仍然得到非零结果。)
通常你必须设置一个连接属性才能使它适用于MySQL(例如,在PHP的PDO驱动程序中有MYSQL_ATTR_FOUND_ROWS
属性)。但是,我的理解是此选项为already enabled in JDBC,因此executeUpdate
应返回匹配行数。目前我无法确认,但您应该很容易进行测试。
答案 1 :(得分:2)
我选择使用选项3来获得可重用性和理智性方面,除非您担心(非常严格且不明显)性能原因引起的一些额外查询。
由于您可能会重复使用该代码来检索其他地方的用户,因此我首先检索该用户,如果找不到,则返回404。然后我调用update和sanity检查更改的行数。最后,我调用检索方法来获取用户并将其编组到响应主体中。它很简单,有效,可读,可预测,可测试,而且最有可能足够快。而且您只是重复使用了检索方法。
答案 2 :(得分:2)
在您的情况下,最好的方法是针对给定的id运行select查询,以验证数据库中是否存在相应的记录。如果存在记录,则可以继续成功流程并运行上面提到的更新和选择查询。否则,如果记录不存在,那么您可以继续执行故障流程(抛出异常等)。
答案 3 :(得分:1)
我有类似的问题。以下是我解决问题的方法
每当它是一个新用户,然后用默认号码标记id(例如51002122),这里51002122永远不是db中的id。所以页面显示“/ 51002122 / user”。当用户的id是51002122然后我会插入db。在插入之后,我使用db的id渲染页面。例如。插入后,页面将是“/ 27 / user”。
对于除51002122以外的所有其他ID(例如/ 12 / user或/ 129 / user),我会在db中进行更新,因为我知道该用户存在于db中。
< / LI> 醇>不确定这是否是正确的方法,但这是有效的。有人能说出更好或更正确的方法。
答案 4 :(得分:1)
我认为最安全的方式是:
SELECT EXISTS(
SELECT *
FROM users
WHERE id = 3 ) as columnCount;
这将返回id = 3的行数。然后你可以返回它并检查columnCount是否为1,然后执行update语句,否则执行其他操作。
答案 5 :(得分:1)
在得出解决方案之前,很少有事情需要考虑。
基于这些考虑,我建议采用以下方法。
updateRecord(Long id, String username)
和getRecord(Long id)
。 @Transaction
)标记为这些方法,如下所示
updateRecord
的交易属性标记为REQUIRED
。getRecord
的交易属性标记为NOT_REQUIRED
,因为这只是一个读取调用。 updateRecord
方法。此方法将返回一个整数。 getRecord
以从数据库中检索更新的记录。 getRecord
。返回给调用客户端的相应错误响应(404 Not Found)。总的来说,这种方法很简洁,不那么杂乱,最重要的是简单而有效(我们只限制更新调用的事务边界)。此外,getRecord
可以独立用作另一个API来检索记录(无事务)。
答案 6 :(得分:0)
我有类似的问题,我应该更新一个表,但在此之前需要检查id是否存在。我使用openjpa并编写方法verifyUser(id),其中id是我需要检查的那个。 OpenJpa findById返回记录。在更新时,它会返回完整的记录,而在添加时,它会返回添加记录的新主键。我不确定它如何用于休眠,但在jpa和hibernate中有许多相似之处。