删除@Embeddable对象时,我遇到了一些问题。
我有以下域类:SwitchVoipTrunkGroup和PrioritizedCodec。后者包含几个可以为空的字段。
class SwitchVoipTrunkGroup {
//...
@CollectionOfElements(fetch = FetchType.LAZY)
@JoinTable(
name = "SWITCH_VOIP_TKG_CODEC",
joinColumns = @JoinColumn(name = "FK_SWITCH_VOIP_TKG_ID")
)
@ForeignKey(name = "FK_CODEC_SWITCH_VOIP_TKG")
private Set<PrioritizedCodec> prioritizedCodecs = new HashSet<PrioritizedCodec>();
//...
}
@Embeddable
public class PrioritizedCodec {
@Column(name = "PRIORITY")
private String priority;
@Column(name = "FAX_MODE")
private String faxMode;
//... some more columns ...
}
当我编辑SwitchVoipTrunkGroup的prioritizedCodecs字段(例如删除条目)并保存实体时,我在Hibernate日志记录中看到以下内容:
13:54:31,919 INFO [STDOUT] Hibernate: delete from T_SWITCH_VOIP_TKG_CODEC where
fk_switch_voip_tkg_id=? and fax_mode=? and priority=?
从this question我理解为什么Hibernate使用where子句中的所有字段。但是,这会产生问题:如果其中一些字段为空,则查询将如下所示:
delete from T_SWITCH_VOIP_TKG_CODEC where fk_switch_voip_tkg_id=1 and fax_mode = ''
and priority =''
但是这不会删除任何记录,因为Hibernate检查空字符串的NULL iso是非常必要的。例如:
delete from T_SWITCH_VOIP_TKG_CODEC where fk_switch_voip_tkg_id=1 and fax_mode
IS NULL and priority IS NULL
(参见here了解更多关于为什么检查空字符串是不够的信息)
关于如何解决这个问题的任何想法?很多人!
答案 0 :(得分:1)
我建议规范化你的数据库,这样你的两个类都成为实体,然后在SwitchVoipTrunkGroup和PrioritizedCodec之间设置一对多的关系,那么你可以设置级联规则,以便Hibernate自动更新PrioritizedCodec类型的元素集合,当你持有SwitchVoipTrungGroup的实例。
@Entity
class SwitchVoipTrunkGroup {
//...
@OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST}, orphanRemoval = true)
@JoinColumn(name = "switchVoipTrunkGroup_id")
@ForeignKey(name = "FK_PrioritizedCodec_SwitchVoipTrunkGroup")
private Set<PrioritizedCodec> prioritizedCodecs = new HashSet<PrioritizedCodec>();
//...
}
@Entity
public class PrioritizedCodec {
@Column(name = "PRIORITY")
private String priority;
@Column(name = "FAX_MODE")
private String faxMode;
//... some more columns ...
}
@Serice("someService")
public class SomeService {
@Autowired
private SwitchVoipTrunkGroupDao trunkDao;
public SwitchVoipTrunkGroup doOperation("criteria") {
SwitchVoipTrunkGroup tg = trunkDao.find("criteroa");
tg.getPrioritizedCodecs().[remove(2)]; //remove should be implemened, that is just lame statement
tg.getPrioritizedCodecs().get(5).setFaxMod("ENABLED");
return trunkDao.save(tg); //hibernate will remove missing elements from PrioritizedCodec table, and will update necessary entities.
}
}
或者,您可以通过@Column注释的属性为priority和faxMode字段指定默认值并强制执行可空约束
@Column(columnDefinition = "VARCHAR(20) default 'NONE'", nullable = false)
private String faxMode;