Как удалить Hibernate @Embeddables, содержащие пустые поля? - PullRequest
3 голосов
/ 22 ноября 2010

При удалении объекта @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 ...
}

Когда я редактирую поле priorVizedCodecs SwitchVoipTrunkGroup (например, удаляя запись) и сохраняю сущность, я вижу в журнале 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=?

С этот вопрос Я понимаю, почему 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

(ср. здесь для получения дополнительной информации о том, почему недостаточно проверки пустой строки)

Есть идеи, как с этим справиться? Многие, спасибо!

1 Ответ

1 голос
/ 03 декабря 2010

Я предлагаю нормализовать вашу базу данных, чтобы оба ваших класса стали объектами, а затем настроить отношение «один ко многим» между 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.
    }
}

В качестве альтернативы, вы можете указать значения по умолчанию для полей priority и faxMode с помощью атрибутов аннотации @Column и применять ограничения, допускающие обнуление

@Column(columnDefinition = "VARCHAR(20) default 'NONE'", nullable = false)
private String faxMode;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...