Код: Выделить всё
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = JOIN_TABLE_NAME)
private List files = new ArrayList();
Автоматически, когда элемент удаляется из списка файлов и объект сохраняется, строка также удаляется из таблицы соединения.
Я хотел бы реализовать такое поведение:
Каждый раз, когда строка удаляется из этой таблицы соединения, проверяйте, нет ли больше строк с B-id в качестве удаленного B-id строки, если поэтому удалите строки из таблицы B, соответствующие этому B-id.
Это можно реализовать несколькими способами. Некоторые из них я пробовал, но они неудовлетворительны или не работают:
Создайте таблицу соединений как отдельный объект и добавьте метод удаления сообщения. Однако этот метод не вызывается:
Код: Выделить всё
@Entity
@PrimaryKeyJoinColumns(
@PrimaryKeyJoinColumn(name = "a_id"),
@PrimaryKeyJoinColumn(name = "b_id")
)
@Table(name = JOIN_TABLE_NAME)
public class ABjoinTable {
@EmbeddedId
private ABId abid;
@Embeddable
public static final class ABId {
@Column(name = "a_id);
public long aid;
@Column(name = "b_id);
public long bid;
}
@PostRemove
public void removeDanglingFiles() {
// not called
}
}
Код: Выделить всё
PostRemoveне будет вызываться (триггер находится на уровне базы данных).
Используйте метод PostUpdate для объекта A и удалите висячие строки вручную, однако строки еще не удаляются из таблицы соединения в контексте обновления после обновления:
Код: Выделить всё
@PostLoad
public void createFilesSnapshot() {
filesSnapshot = new ArrayList(this.files);
}
@PostUpdate
public void removeDanglingFiles() {
// if there are no more references to other Bids, delete that B
val removed = filesSnapshot.stream()
.filter(b -> !this.files.contains(b))
.map(PersistentObject::getId)
.collect(Collectors.toSet());
try (val em = JPAutil.getEntityManager()) {
val tx = em.getTransaction();
tx.begin();
for (val rId : removed) {
val q = em.createQuery("SELECT a" +
" FROM A a JOIN a.files b" +
" WHERE b.id = :bId", B.class);
q.setParameter("bId", rId);
val result = q.getResultList();
if (result.size() == 0) { // at this point in post load, join table row is not yet removed, so size is >= 1
em.remove(...);
}
}
tx.commit();
} catch (final Exception e) {
}
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... selink-jpa
Мобильная версия