如何防止 Hibernate 更新 NULL 值
Posted
技术标签:
【中文标题】如何防止 Hibernate 更新 NULL 值【英文标题】:How can I prevent Hibernate from updating NULL values 【发布时间】:2011-11-22 23:18:12 【问题描述】:在保存休眠对象时,休眠中是否有设置忽略空值属性?
注意 就我而言,我通过 Jackson 将 JSON 反序列化为 Hibernate Pojo。
JSON 只包含 Pojo 的一些字段。如果我保存 Pojo,则不在 JSON 中的字段在 Pojo 中为 null 并休眠更新它们。
我遇到了updateable=false
设置,但这不是 100% 的解决方案。
http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-property
也许有人有别的想法……
注意 2:
根据 Hibernate Docs,dynamicUpdate
注释正是这样做的
dynamicInsert / dynamicUpdate(默认为 false): 指定应在运行时生成 INSERT / UPDATE SQL 并且只包含值不为空的列。
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-class
如果您通过dynamic-update
在 XML 中定义它就够有趣了,文档中没有提到 NULL 值的处理。
dynamic-update(可选 - 默认为 false): 指定 UPDATE SQL 应该 > 在运行时生成,并且只能包含值已更改的列。
由于我同时使用注释 AND xml 配置,hibernate 似乎忽略了我的 dynamicUpdate=true
注释。
【问题讨论】:
您可以使用动态更新来避免 SQL 中出现尚未更新的属性,但通常建议仅在实体具有过多属性时使用此设置(列 > 50)[参考: Java Persistence with Hibernate 2006 edition]。 @hvgotcodes 正确地指出,如果字段永远不会被持久化,您不必映射字段。 【参考方案1】:您应该首先使用数据库中的主键加载对象,然后在其上复制或反序列化 JSON。
hibernate 无法确定值为 null 的属性是否已显式设置为该值或已被排除。
如果是插入,那么 dynamic-insert=true 应该可以工作。
【讨论】:
引导我走向正确的方向。最好是加载现有对象并相应地更新此对象。杰克逊甚至对 wiki.fasterxml.com/JacksonFeatureUpdateValue 有一个默认行为 我的数据库中没有任何空值。因此,没有人永远不会明确地将任何内容设置为空。我还有其他解决方案吗? @gkamal【参考方案2】:我在谷歌上搜索了很多关于这个的,但没有适合我的解决方案。所以,我使用了一个不优雅的解决方案来解决它。
public void setAccount(Account a) throws HibernateException
try
Account tmp = (Account) session.
get(Account.class, a.getAccountId());
tmp.setEmail(getNotNull(a.getEmail(), tmp.getEmail()));
...
tmp.setVersion(getNotNull(a.getVersion(), tmp.getVersion()));
session.beginTransaction();
session.update(tmp);
session.getTransaction().commit();
catch (HibernateException e)
logger.error(e.toString());
throw e;
public static <T> T getNotNull(T a, T b)
return b != null && a != null && !a.equals(b) ? a : b;
我收到一个Object a
,其中包含很多字段。那些字段可能是null
,但我不想将它们更新到mysql。
我从db得到一个tmp Obejct
,通过getNotNull
方法改变字段,然后更新Object。
a Chinese description edition
【讨论】:
【参考方案3】:我遇到了这个问题,我做了一个解决方法来帮助自己解决这个问题。可能有点难看,但也可能对你有用。如果有人觉得有一个很好的调整,可以随意添加。请注意,该解决方法适用于有效的实体类,并且其某些字段包含可为空的属性。这样做的好处是它减少了查询的数量。
public String getUpdateJPQL(Object obj, String column, Object value) throws JsonProcessingException, IOException
//obj -> your entity class object
//column -> field name in the query clause
//value -> value of the field in the query clause
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(obj);
Map<String, Object> map = mapper.readValue(json, Map.class);
Map format = new HashMap();
if (value instanceof String)
value = "'" + value + "'";
map.keySet()
.forEach((str) ->
Object val = map.get(str);
if (val != null)
format.put("t.".concat(str), "'" + val + "'");
);
String formatStr = format.toString();
formatStr = formatStr.substring(1, formatStr.length() - 1);
return "update " + obj.getClass()
.getSimpleName() + " t set " + formatStr + " where " + column + " = " + value + "";
示例:对于实体类型User
,字段为:userId
、userName
& userAge
; getUpdateJPQL(user, userId, 2)
的结果查询应该是update User t set t.userName = 'value1', t.userAge = 'value2' where t.userId = 2
请注意,您可以在 userId
字段上使用 json 注释(如 @JsonIgnore
)在反序列化(即生成的查询)中将其排除。
然后,您可以使用 entityManager 或休眠会话运行查询。
【讨论】:
以上是关于如何防止 Hibernate 更新 NULL 值的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate:如何使用 HQL 设置 NULL 查询参数值?
hibernate在Oracle中插入数据,默认字段被设置为null的问题解决