I have a situation where an entity could use another entity, and it could be used by another, so i have defined a ManyToMany relation that reference the same entity, so i could have listUse and listUsedBy, and both are persisted in the same table entity_usage :
@ManyToMany
@JoinTable(name = "entity_usage",
joinColumns = {
@JoinColumn(name = "id_use", referencedColumnName = "id")},
inverseJoinColumns = {
@JoinColumn(name = "id_used_by", referencedColumnName = "id")})
private List<Entity> listUse;
@ManyToMany
@JoinTable(name = "entity_usage",
joinColumns = {
@JoinColumn(name = "id_use_by", referencedColumnName = "id")},
inverseJoinColumns = {
@JoinColumn(name = "id_use", referencedColumnName = "id")})
private List<Entity> listUsedBy;
Exemple : Entity A could use Entity B and C, so Entity B and C are used by A. Now my problem is when i add B and C to listUse, they are persisted in entity_usage, but when try to display listUsedBy i have to redeploy my project, otherwise listUsedBy remains empty, is there a way to refresh listUsedBy when persist my entity without having to redeploy my project.
This is the general approach:
@Entity
public class SomeEntity
{
@ManyToMany
@JoinTable(name = "entity_usage",
joinColumns = @JoinColumn(name = "using_id"),
inverseJoinColumns = @JoinColumn(name = "used_by_id"))
private Set<SomeEntity> using = new LinkedHashSet<>();
@ManyToMany(mappedBy = "using")
private Set<SomeEntity> usedBy = new LinkedHashSet<>();
public void addUsing(SomeEntity entity)
{
this.using.add(entity);
entity.usedBy.add(this);
}
public void addUsedBy(SomeEntity entity)
{
this.usedBy.add(entity);
entity.using.add(this);
}
}
and it's used:
public void someMethod(long parentEntityId, long childEntityId)
{
EntityManager em = getSomeEntityManager();
SomeEntity parentEntity = em.find(SomeEntity.class, parentEntityId);
SomeEntity childEntity = em.find(SomeEntity.class, childEntityId);
parentEntity.addUsing(childEntity);
}
typically this is a transactional EJB method.
Note that there's no need to em.merge
anything, since entities are already managed by em.find
.
Anyway, whichever method you'll use to manage your entities (query, find, persist, merge), remember that's important to call addUsing
/addUsedBy
only when both entities are managed.
This is one of the main incoherences that ORM logic cannot handle by its own: you have to inform both entities (parent and child) of their relation.
It's not sufficient to set the relation only on one side - if you only say that A is parent of B, B still doesn't know who is its parent.
However, there exists alternative approaches, like setting only the owning side of the relation (parent.getChildren().add(child)
), flush, and refresh the child.
Nevertheless (as I experienced very well on my skin) the alternatives are very hard to handle in real world complex applications.
As a side note, I'd use Set
instead of List
for the relation, unless you need some kind of insertion-order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With