如何删除包含可空字段的Hibernate @Embeddables?

时间:2010-11-22 14:21:59

标签: java hibernate jpa

删除@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了解更多关于为什么检查空字符串是不够的信息)

关于如何解决这个问题的任何想法?很多人!

1 个答案:

答案 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;