Есть две сущности (политики паролей и группы):
@Entity
@Table(name = "sys_password_policy", schema = "oauth")
public class SysPasswordPolicyEntity implements Serializable {
private Long policyId;
private String policyName;
private Set<SysGroupEntity> sysGroupsByPolicyId;
// ...
@OneToMany(mappedBy = "sysPasswordPolicyByPasswordPolicyId", fetch = FetchType.LAZY)
public Set<SysGroupEntity> getSysGroupsByPolicyId() {
return sysGroupsByPolicyId;
}
public void setSysGroupsByPolicyId(Set<SysGroupEntity> sysGroupsByPolicyId) {
this.sysGroupsByPolicyId = sysGroupsByPolicyId;
}
}
@Entity
@Table(name = "sys_group", schema = "oauth")
public class SysGroupEntity implements Serializable {
private Long groupId;
private String groupName;
private SysPasswordPolicyEntity sysPasswordPolicyByPasswordPolicyId;
//...
@ManyToOne
@JoinColumn(name = "password_policy_id", referencedColumnName = "policy_id")
public SysPasswordPolicyEntity getSysPasswordPolicyByPasswordPolicyId() {
return sysPasswordPolicyByPasswordPolicyId;
}
public void setSysPasswordPolicyByPasswordPolicyId(SysPasswordPolicyEntity sysPasswordPolicyByPasswordPolicyId) {
this.sysPasswordPolicyByPasswordPolicyId = sysPasswordPolicyByPasswordPolicyId;
}
}
Нужно, чтобы:
При создании политики можно было ей назначить какие-то группы (группы при этом не должны создаваться, и у них не должны обновляться никакие поля, кроме sysPasswordPolicyByPasswordPolicyId
)
При обновлении политики можно было удалить из списка группу, а также добавить её в список (при этом не нужно, чтобы группы удалялись из базы, создавались в базе, и не нужно, чтобы у них в базе обновлялись все поля, кроме sysPasswordPolicyByPasswordPolicyId
; нужно, чтобы при удалении из списка значение поля sysPasswordPolicyByPasswordPolicyId
становилось null
, при добавлении - этому полю присваивалась ссылка на текущую группу)
Как обычно решаются такие задачи? (вроде ситуация стандартная, и часто встречается)
P.S. Пытался искать в интернете, но по моей ситуации сложно что-то найти, а по связанным общим темам пока ничего не нашёл.
PSS Пока реализовано так:
@Override
public SysPasswordPolicyEntity persist(SysPasswordPolicyEntity entity) {
setRelationObjects(entity, false);
return super.persist(entity);
}
@Override
public SysPasswordPolicyEntity update(SysPasswordPolicyEntity entity) {
setRelationObjects(entity, false);
return super.persist(entity);
}
private void setRelationObjects(SysPasswordPolicyEntity entity, boolean isUpdate) {
if (entity == null)
return;
final Set<SysGroupEntity> sysGroupsFromRest = entity.getSysGroupsByPolicyId();
if (!isUpdate) {
sysGroupsFromRest.stream() // добавление нового
.filter(Objects::nonNull)
.forEach(
sysGroupEntity -> {
sysGroupEntity.setSysPasswordPolicyByPasswordPolicyId(entity);
final Long groupId = sysGroupEntity.getGroupId();
if (groupId != null) {
Optional.ofNullable(sysGroupDao.findById(groupId))
.ifPresent(sysGroupEntityfromDB -> {
sysGroupEntityfromDB.setSysPasswordPolicyByPasswordPolicyId(entity);
sysGroupDao.update(sysGroupEntityfromDB);
});
}
}
);
} else {
final Session session = getSession();
final Set<SysGroupEntity> sysGroupEntitiesFromDB = Optional.ofNullable(findById(entity.getPolicyId()))
.map(entityFromDB -> {
session.evict(entityFromDB);
return entityFromDB;
})
.map(SysPasswordPolicyEntity::getSysGroupsByPolicyId)
.orElse(Set.of());
sysGroupEntitiesFromDB.stream()
.filter(Objects::nonNull)
.filter(Predicate.not(sysGroupsFromRest::contains))
.forEach(
sysGroupEntityFromDB ->
Optional.ofNullable(sysGroupDao.findById(sysGroupEntityFromDB.getGroupId()))
.ifPresent(sysGroupEntityfromDB -> {
session.evict(sysGroupEntityfromDB.getSysPasswordPolicyByPasswordPolicyId());
sysGroupEntityfromDB.setSysPasswordPolicyByPasswordPolicyId(null);
sysGroupDao.update(sysGroupEntityfromDB);
})
);
sysGroupsFromRest.stream()
.filter(Objects::nonNull)
.filter(Predicate.not(sysGroupEntitiesFromDB::contains))
.forEach(sysGroupEntityFromREST -> {
Optional.ofNullable(sysGroupEntityFromREST.getGroupId())
.map(sysGroupDao::findById)
.ifPresent(sysGroupEntityfromDB -> {
sysGroupEntityfromDB.setSysPasswordPolicyByPasswordPolicyId(entity);
sysGroupDao.update(sysGroupEntityfromDB);
});
});
}
}
Судя по описанной структуре основная сущность - группа. Данные храняться в поле sysPasswordPolicyByPasswordPolicyId для писанной связи - поэтому вы назначаете политику группе а не наоборот.
Соответственно когда вы меняете политику, то это не должно менять ссылки на нее.
Если надо поменять ссылку на политику, то это по сути отдельная операция где обновляется не политика а группа.
Если по бизнес требованиям надо проделать какую-либо работу с ссылками из-за изменения политики, то эту логику можно вынести в слушатель. Т.е. сохранение политики в конце публикует событие о том что политика изменена, соответствующий слушатель перехватывает это изменение и вызывает необходимый метод в сервисе работы с группами.Таким образом вы не привязываете сервис политики к сервису групп и будут поделены зоны ответственности.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Задача: найти файлы в каталоге и подкаталогах, и сохранить в папку result