如果其参数为空,Mybatis 将跳过更新特定列
Mybatis skipping update the specific column if its parameter is null
我在 MAPPER 中有以下更新查询
<update id="updTest" parameterType="TestDTO">
<![CDATA[
UPDATE TEST_USER
SET
EMAIL = #{email, jdbcType=VARCHAR}
, USERNAME = #{username, jdbcType=VARCHAR}
, PASSWORD = #{password, jdbcType=VARCHAR}
, DOMAIN = #{domain, jdbcType=VARCHAR}
, COMPANY = #{company, jdbcType=VARCHAR}
, DEPARTMENT = #{department, jdbcType=VARCHAR}
, JOBTITLE = #{jobtitle, jdbcType=VARCHAR}
, SIZE = #{size, jdbcType=INTEGER}
, SEX = #{sex, jdbcType=VARCHAR}
, BIRTH = #{birth, jdbcType=VARCHAR}
, MOBILE = #{mobile, jdbcType=VARCHAR}
, STATUS = #{status, jdbcType=VARCHAR}
, AUTH_KEY = #{authKey, jdbcType=VARCHAR}
, UPDATE_DATE = SYSDATE
, UPDATE_ID = #{updateId, jdbcType=VARCHAR}
, CREATE_DATE = SYSDATE
, CREATE_ID = #{createId, jdbcType=VARCHAR}
, DEL_YN = #{delYn, jdbcType=VARCHAR}
, DEL_ID = #{delId, jdbcType=VARCHAR}
WHERE USERNAME= #{username, jdbcType=VARCHAR}
OR EMAIL = #{email, jdbcType=VARCHAR}
OR AUTH_KEY = #{authKey, jdbcType=VARCHAR}
]]>
</update>
我想要实现的目标 是跳过参数为空的列的更新。
我有一个表格,用户将在下面填写这些表格。
- 职位
- 尺寸
- 手机
- 出生
- 性别
- 状态
这是附加信息,在成功登录后出现。但是当用户填写表单并提交时,更新过程非常有效。
但现有的EMAIL, USERNAME, PASSWORD
和其他设置为null
除了表格中的那6个字段。这让我发疯,我一直认为如果它的参数是 null
,Mybatis 将跳过更新字段。有什么特殊配置吗?
你抱怨的是 SQL,不是 MyBatis。如果您的更新语句包括 SET mobile = null,SQL 将执行此操作。
但是 MyBatis 通过 if 语句提供了很好的动态 SQL 设施。参见 https://mybatis.github.io/mybatis-3/dynamic-sql.html。这应该会让您走上定制解决方案的正确轨道。
此外,请考虑更改您的模式(如果它在您的控制之下)。应该有一个数字 userId 字段作为主键,按序列或类似方式分配。或者,在这种情况下,USERNAME 是通用密钥。两者都会简化您的 WHERE 子句,并且几乎是标准做法。就目前而言,EMAIL 似乎是主键的一部分,因此更改电子邮件地址将意味着他们成为不同的用户。
还有最后一条评论。我从未在 MyBatis SQL 查询中使用过 CDATA,但它可能没有害处。
我认为您需要重新审视您的要求,因为有些要求没有多大意义。
- 你的 WHERE 子句真的很奇怪。如果一个六口之家都共享同一个电子邮件地址,您真的要在登录时更新所有六个记录吗?您需要确定一个唯一的主键,USERNAME 非常有意义。
- 决定将 USERNAME 作为 table 的唯一主键后,您可以删除 WHERE 子句的最后两行并将 USERNAME 从 SET 列表中删除,因为它永远不会更改。
- 您将如何处理现有用户决定不再拥有手机的情况?在这种情况下,您似乎确实需要将 MOBILE 设置为 null。
- AUTH_TOKEN 字段在数据库中很奇怪。授权令牌通常仅在登录会话期间有效 - 但我可能误解了您的用例。
所以回到你的评论,我建议你写一个 MyBatis 更新,它只更新你表单上的六个字段(名称类似于 updateLoginFields),带有一个仅指定 USERNAME 的 WHERE 子句。您无需担心空值,因为您可以控制表示层中的可选内容。
我在 MAPPER 中有以下更新查询
<update id="updTest" parameterType="TestDTO">
<![CDATA[
UPDATE TEST_USER
SET
EMAIL = #{email, jdbcType=VARCHAR}
, USERNAME = #{username, jdbcType=VARCHAR}
, PASSWORD = #{password, jdbcType=VARCHAR}
, DOMAIN = #{domain, jdbcType=VARCHAR}
, COMPANY = #{company, jdbcType=VARCHAR}
, DEPARTMENT = #{department, jdbcType=VARCHAR}
, JOBTITLE = #{jobtitle, jdbcType=VARCHAR}
, SIZE = #{size, jdbcType=INTEGER}
, SEX = #{sex, jdbcType=VARCHAR}
, BIRTH = #{birth, jdbcType=VARCHAR}
, MOBILE = #{mobile, jdbcType=VARCHAR}
, STATUS = #{status, jdbcType=VARCHAR}
, AUTH_KEY = #{authKey, jdbcType=VARCHAR}
, UPDATE_DATE = SYSDATE
, UPDATE_ID = #{updateId, jdbcType=VARCHAR}
, CREATE_DATE = SYSDATE
, CREATE_ID = #{createId, jdbcType=VARCHAR}
, DEL_YN = #{delYn, jdbcType=VARCHAR}
, DEL_ID = #{delId, jdbcType=VARCHAR}
WHERE USERNAME= #{username, jdbcType=VARCHAR}
OR EMAIL = #{email, jdbcType=VARCHAR}
OR AUTH_KEY = #{authKey, jdbcType=VARCHAR}
]]>
</update>
我想要实现的目标 是跳过参数为空的列的更新。
我有一个表格,用户将在下面填写这些表格。
- 职位
- 尺寸
- 手机
- 出生
- 性别
- 状态
这是附加信息,在成功登录后出现。但是当用户填写表单并提交时,更新过程非常有效。
但现有的EMAIL, USERNAME, PASSWORD
和其他设置为null
除了表格中的那6个字段。这让我发疯,我一直认为如果它的参数是 null
,Mybatis 将跳过更新字段。有什么特殊配置吗?
你抱怨的是 SQL,不是 MyBatis。如果您的更新语句包括 SET mobile = null,SQL 将执行此操作。
但是 MyBatis 通过 if 语句提供了很好的动态 SQL 设施。参见 https://mybatis.github.io/mybatis-3/dynamic-sql.html。这应该会让您走上定制解决方案的正确轨道。
此外,请考虑更改您的模式(如果它在您的控制之下)。应该有一个数字 userId 字段作为主键,按序列或类似方式分配。或者,在这种情况下,USERNAME 是通用密钥。两者都会简化您的 WHERE 子句,并且几乎是标准做法。就目前而言,EMAIL 似乎是主键的一部分,因此更改电子邮件地址将意味着他们成为不同的用户。
还有最后一条评论。我从未在 MyBatis SQL 查询中使用过 CDATA,但它可能没有害处。
我认为您需要重新审视您的要求,因为有些要求没有多大意义。
- 你的 WHERE 子句真的很奇怪。如果一个六口之家都共享同一个电子邮件地址,您真的要在登录时更新所有六个记录吗?您需要确定一个唯一的主键,USERNAME 非常有意义。
- 决定将 USERNAME 作为 table 的唯一主键后,您可以删除 WHERE 子句的最后两行并将 USERNAME 从 SET 列表中删除,因为它永远不会更改。
- 您将如何处理现有用户决定不再拥有手机的情况?在这种情况下,您似乎确实需要将 MOBILE 设置为 null。
- AUTH_TOKEN 字段在数据库中很奇怪。授权令牌通常仅在登录会话期间有效 - 但我可能误解了您的用例。
所以回到你的评论,我建议你写一个 MyBatis 更新,它只更新你表单上的六个字段(名称类似于 updateLoginFields),带有一个仅指定 USERNAME 的 WHERE 子句。您无需担心空值,因为您可以控制表示层中的可选内容。