使用@CollectionTable 的 Hibernate 在更新时删除具有相同布尔值的集合对象
Hibernate with @CollectionTable removes the objects of set with same boolean value on update
我有以下结构:
public class Profile {
...
@ElementCollection(targetClass = ProfileFieldImpl.class, fetch = FetchType.EAGER)
@CollectionTable(name = "profileField", joinColumns = @JoinColumn(name = "profileId"))
@OrderColumn(name = "fieldName")
private Set<ProfileField> fields;
}
@Embeddable
public class ProfileFieldImpl {
@AttributeOverride(name = "id", column = @Column(name = "rofileFieldId", nullable = false))
private Long profileFieldId;
private String name;
}
现在我要添加一个新列:publicField
还添加了 equals
和 hashCode
方法。
public class ProfileFieldImpl {
@AttributeOverride(name = "id", column = @Column(name = "rofileFieldId", nullable = false))
private Long profileFieldId;
private String name;
private boolean publicField;
@Override
public final boolean equals(final Object o) {
if (o == this) {
return true;
} else if (o == null || !(o instanceof ProfileFieldImpl)) {
return false;
} else {
final ProfileFieldImpl other = (ProfileFieldImpl) o;
return EqualsUtil.equalsNullable(getName(), other.getName()) && EqualsUtil.equalsNullable(isPublicField(), other.isPublicField()));
}
}
@Override
public final int hashCode() {
return HashCodeUtil.seed(HashCodeUtil.SEED_13).with(name).with(publicField).hashCode();
}
}
添加以下字段(数据库字段):
1. name = "Field1", publicField = '0'
2. name = "Field2", publicField = '0'
3. name = "Field3", publicField = '1'
4. name = "Field4", publicField = '1'
我如何进行更新:
....
final ProfileImpl profile = getEntityManager().find(Profile.java, profileId, LockModeType.NONE);
final Set<ProfileField> fields = profile.getFields();
fields.stream().filter(field -> field.getName().equals(currentFieldName)).forEach(field -> {
field.setName(updatedProfileField.getName());
field.setPublicField(updatedProfileField.isPublicField());
});
getEntityManager().merge(profile);
问题:
当我尝试更新 field3
时,field4
被删除;
当我尝试更新 field1
时,field2
被删除了。
有人有什么建议吗?
这听起来像是一个错误。所以你需要:
- 提供一个replicating test case
- 打开一个 Jira 问题
我终于找到了问题以及解决方案。
因为使用布尔值作为 primitive
而不是 object
是那个问题。
解决方案是使用布尔包装器而不是原语。
private Boolean publicField;
现在无需删除任何其他对象即可正常工作。
我有以下结构:
public class Profile {
...
@ElementCollection(targetClass = ProfileFieldImpl.class, fetch = FetchType.EAGER)
@CollectionTable(name = "profileField", joinColumns = @JoinColumn(name = "profileId"))
@OrderColumn(name = "fieldName")
private Set<ProfileField> fields;
}
@Embeddable
public class ProfileFieldImpl {
@AttributeOverride(name = "id", column = @Column(name = "rofileFieldId", nullable = false))
private Long profileFieldId;
private String name;
}
现在我要添加一个新列:publicField
还添加了 equals
和 hashCode
方法。
public class ProfileFieldImpl {
@AttributeOverride(name = "id", column = @Column(name = "rofileFieldId", nullable = false))
private Long profileFieldId;
private String name;
private boolean publicField;
@Override
public final boolean equals(final Object o) {
if (o == this) {
return true;
} else if (o == null || !(o instanceof ProfileFieldImpl)) {
return false;
} else {
final ProfileFieldImpl other = (ProfileFieldImpl) o;
return EqualsUtil.equalsNullable(getName(), other.getName()) && EqualsUtil.equalsNullable(isPublicField(), other.isPublicField()));
}
}
@Override
public final int hashCode() {
return HashCodeUtil.seed(HashCodeUtil.SEED_13).with(name).with(publicField).hashCode();
}
}
添加以下字段(数据库字段):
1. name = "Field1", publicField = '0'
2. name = "Field2", publicField = '0'
3. name = "Field3", publicField = '1'
4. name = "Field4", publicField = '1'
我如何进行更新:
....
final ProfileImpl profile = getEntityManager().find(Profile.java, profileId, LockModeType.NONE);
final Set<ProfileField> fields = profile.getFields();
fields.stream().filter(field -> field.getName().equals(currentFieldName)).forEach(field -> {
field.setName(updatedProfileField.getName());
field.setPublicField(updatedProfileField.isPublicField());
});
getEntityManager().merge(profile);
问题:
当我尝试更新 field3
时,field4
被删除;
当我尝试更新 field1
时,field2
被删除了。
有人有什么建议吗?
这听起来像是一个错误。所以你需要:
- 提供一个replicating test case
- 打开一个 Jira 问题
我终于找到了问题以及解决方案。
因为使用布尔值作为 primitive
而不是 object
是那个问题。
解决方案是使用布尔包装器而不是原语。
private Boolean publicField;
现在无需删除任何其他对象即可正常工作。