Reputation: 46472
I have a simple
public class SomeEntity {
@Id private Integer id;
@NaturalId private User owner;
@NaturalId(mutable=true) private String name;
...
}
and the natural id creates a unique key (good!) and it makes owner
immutable from hibernate. That's a good thing, too, however, once in a blue moon, an admin needs to change the owner. So I seem to be forced to make it also mutable, which is really dislike.
I could use a plain SQL to overcome it, but this would mean lying, which I dislike, too, as it could fool hibernate into doing something wrong.
I'm looking for a clean way to state something like "immutable except when I say" (though I'm pessimistic concerning it's possible). I'm also curious, what are the disadvantages of the alternatives.
Upvotes: 2
Views: 665
Reputation: 4624
In mine oppinion: this situations shows that owner and name are not natural ids anymore. They are simply the properties, which from the service level could be changed from time to time, and there is a limit on having unique pair of owner, name
values from business level perspective. So the "immutable except when I say" situation should be resolved on "business"-service level: i.e. owner becomes mutable, and inside of your services you are creating separate method to modify it, other methods should not modify this property. i.e.:
@Secured(ADMIN_ONLY_ACCESS)
public SomeEntity modifyAdministrative(SomeEntity entity) {
//here you allow to modify owner
}
public SomeEntity modify(SomeEntity entity) {
// here owner should be used as readonly property
// and you can controll this only on your own,
// hibernate is not able to support you anymore with immutability control
}
Or you can map your data of some entity tables to second different entity, and reuse the NaturalId
behaviours provided by hibernate, i.e.
public class SomeEntity {
// Keep this for general usage
@Id private Integer id;
@NaturalId private User owner;
@NaturalId(mutable=true) private String name;
...
}
public class SomeEntityForAdmin {
// use this for administrative usage
@Id private Integer id;
private User owner;
private String name;
...
}
SomeEntityForAdmin
is used only for administrative situations, when it is required to change the owner
. And all the rest of code is kept as it is.
But be warned: you will have complex issues with caches (you have to create proper invalidation strategies for your caches, once changes in SomeEntityForAdmin
or SomeEntity
happend), and it becomes a complete mess when in same transaction both SomeEntity
and SomeEntityForAdmin
are involved.
Upvotes: 2