3

When deleting an @Embeddable object, I run into some problems.

I have the following domain classes: SwitchVoipTrunkGroup and PrioritizedCodec. The latter contains several fields that are nullable.

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 ...
}

When I edit SwitchVoipTrunkGroup's prioritizedCodecs field (e.g. by deleting an entry) and save the entity, I see the following in my Hibernate logging:

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=?

From this question I understand why Hibernate uses all the fields in the where clause. However, this gives problems: in case some of these fields are empty, the query will look like so:

delete from T_SWITCH_VOIP_TKG_CODEC where fk_switch_voip_tkg_id=1 and fax_mode = '' 
and priority =''

This will however not delete any records, as what is really necessary is for Hibernate to check for NULL iso for an empty string. For example:

delete from T_SWITCH_VOIP_TKG_CODEC where fk_switch_voip_tkg_id=1 and fax_mode
IS NULL and priority IS NULL

(cf. here for more info on why checking for an empty string does not suffice)

Any ideas on how to tackle this? Many thx!

Community
  • 1
  • 1
David Bulté
  • 2,988
  • 3
  • 31
  • 43
  • Is there a reason why you can't set the values of these attributes to null in your entity before doing the delete operation? – Jim Tough Nov 22 '10 at 15:05
  • The fact that they are null is exactly the problem, because this makes Hibernate check for empty strings in the where clause. – David Bulté Nov 23 '10 at 06:57
  • Thing is, the concept of @Embeddable objects is that their lifecycle is tied to that of their parent - deleting them without deleting their parent seems off. – Jean Hominal Dec 03 '10 at 20:26

1 Answers1

1

I suggest to normalize your database, so both your classes become entities, and then to setup One-to-Many relation between SwitchVoipTrunkGroup and PrioritizedCodec, then you may setup cascading rules so Hibernate automatically updates collection of elements of PrioritizedCodec type, when you persist instance of 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.
    }
}

Alternatively, you may specify default values for priority and faxMode fields via attributes of @Column annotation and enforce nullable constraints

@Column(columnDefinition = "VARCHAR(20) default 'NONE'", nullable = false)
private String faxMode;
Seego
  • 106
  • 6