如何在 Java 中仅更新 @Transactional 方法中更改的字段?
Posted
技术标签:
【中文标题】如何在 Java 中仅更新 @Transactional 方法中更改的字段?【英文标题】:How can I update only changed fields in my @Transactional method in Java? 【发布时间】:2020-09-01 09:57:17 【问题描述】:亲爱的开发者们好!我需要解决一些与我的方法相关的问题。 我需要创建一个允许我更改对象的编辑/更新方法。
其中一个条件是只有用户更改的字段才能在数据库中更改。不应覆盖所有字段。 示例:旧值名称 -> “Jack”,新值名称 -> “Bob”,应该更改 . 但是,如果旧值是 name -> " Jack ",而新值是 name -> "Jack",则不应覆盖该字段,因为值相等。
我需要我的方法只检查和更改已更改的字段并在数据库中插入更改。
我尝试使用 sql 完成任务,但不幸的是我不知道如何设置值 (如果新值现在与 DB 中的值相同,则不执行任何更新) :
@Transactional(transactionManager = TransactionManagerConfig.TX_MANAGER_MAIN)
public void editUserContacts(User user)
Connection connection = DataSourceUtils.getConnection(mainDataSource);
String sql = "UPDATE `" + userSchema + "`.l_user " +
" SET user_phone_number = @phoneNumber," +
"firstname = @fullName," +
"user_country = @userCountry," +
"house_phone_number = @phoneAlternative," +
" WHERE l_user_id=? , " +
"user_phone_number != @phoneNumber OR IS NULL," +
"firstName != @fullName OR IS NULL," +
"user_country != @userCountry OR IS NULL," +
"house_phone_number != @phoneAlternative OR IS NULL,;
try (
PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
)
statement.executeUpdate();
statement.getUpdateCount();
catch (SQLException e)
throw new DAOException(e);
也许我需要先执行 SELECT,或者使用 equals 比较每个字段?请告诉我至少一个值的示例,我怎样才能正确地执行我的任务?
P.S 如果新值不等于旧值,我想更新我的值。但是如果新旧值相等,则什么都不会发生
非常感谢您的帮助!
【问题讨论】:
【参考方案1】:示例:旧值名称 -> “Jack”,新值名称 -> “Bob”,应该更改 .但是,如果旧值是 name -> " Jack ",而新值是 name -> "Jack",则不应覆盖该字段,因为值相等。
别管它。 mysql 足够聪明,只有当列的值真正改变时,它才会更新列。
例子:
看 - 有 2 行,只有一行中的值发生了变化。和 MySQL 报告
1 行受影响
和
匹配行:2 更改:1
即事实上没有改变值的行没有改变。
【讨论】:
在一种情况下,SQL 确实 关心。如果 all 值未更改,则可能需要避免更新任何行:以节省服务器负载、避免触发触发器或避免自动时间戳更新。 @Akina,很高兴知道这一点。但是正如 cmets 中提到的,如果它说1 row affected
,那么 trigger
是否仍然对两行都执行并且还会发生“自动 tmestamp 更新”(如果有的话)吗?虽然不确定server load
部分。
@Sujitmohanty30 触发器是否仍然对两行都执行并且还会发生“自动 tmestamp 更新”(如果有)? 如果更新查询成功执行,那么自动使用的时间戳值将是更新并为所有匹配的行触发触发器。如果更新失败(由于 CHECK 约束或其他原因),则查询和触发的触发器所做的所有更改(包括自动使用的时间戳更新)都将被回滚。【参考方案2】:
如果我理解正确,您只会在新值不是NULL
时更新表中的值。但是,只有部分列可能会受到影响。为此,请使用COALESCE()
:
UPDATE " + userSchema + ".l_user
SET user_phone_number = COALESCE(@phoneNumber, user_phone_number),
firstname = COALESCE(@fullName, firstname),
user_country = COALESCE(@userCountry, user_country),
house_phone_number = COALESCE(@phoneAlternative, house_phone_number),
WHERE l_user_id = ? AND
not (user_phone_number <=> @phoneNumber and
firstName <=> @fullName and
user_country <=> @userCountry and
house_phone_number <=> @phoneAlternative
);
这将尝试仅更新四个值之一已更改的行。 <=>
是 NULL
-safe 比较运算符。
您的查询尝试有多个错误。
WHERE
子句无法识别,
。这只是一个语法错误
OR IS NULL
不是有效的 SQL。这是语法错误。
WHERE
子句前还有一个逗号,这是另一个语法错误。
【讨论】:
如果新值不等于旧值,我想更新我的值。但如果新旧值相等,则什么都不会发生以上是关于如何在 Java 中仅更新 @Transactional 方法中更改的字段?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 swift 中仅为唯一值更新 TableView 行?
如何在 android 应用程序中仅从服务器获取更新的数据?
如何访问以前的状态,并使用它在单个状态设置器调用中仅更新某些对象属性?