В моем приложении я использую проекции для сопоставления *Entity
объектов с упрощенными или измененными версиями фактической записи в базе данных.
Однако у меня есть конкретный случай использования, когда Я обязан заменить определенное значение из одного из вложенных прогнозов. Так как это интерфейсы и они также проксируются Spring, я не уверен, что то, что я хочу, действительно возможно, но я приведу это к одному очень простому примеру:
Предположим, у меня есть UserEntity
и User
проекция. Для моей User
проекции я могу просто выполнить:
User user = this.userEntityRepository.findById(userId);
Однако, если я хочу что-то изменить, я не уверен, возможно ли это. А именно, я не могу сделать что-то вроде этого:
if (user.getAge() < 18) {
user.setDisplayName(null);
}
Теперь я знаю, что мог бы создать анонимный класс new User() { .. }
и просто передать требуемые значения, но в моем случае объекты вложены и следовательно, это не вариант.
Вопрос
Есть ли другой способ заменить значение, например, displayName
, как указано выше, без использования анонимного класса?
Удачный пример
Чтение следующего не является действительно необходимым, но для того, чтобы проиллюстрировать мою проблему более подробно, я псевдокодировал пример, который немного ближе показывает, в чем проблема в моем конкретном случае.
У нас есть простое UserEntity
:
@Entity
@Table(name = "app_user")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String firstName;
@Column
private String lastName;
@Column
private Integer age;
// Setter & Getter ..
}
@Entity
@Table(name = "event")
public class EventEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "event")
private List<EventAttendeeEntity> attendees;
// ..
}
У нас есть таблица, которая отображает пользователей на события:
@Entity
@Table(name = "attendee")
public class AttendeeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
private EventEntity event;
@ManyToOne
private UserEntity user;
// ..
}
Кроме того, у нас есть прогнозы для этих сущности, которые мы готовим как представления для наших клиентов:
/*
* Projection for User
*/
public interface User {
// All the properties ..
}
/*
* Projection for AttendeeEntity
*/
public interface Attendee {
Long getId();
User getUser();
}
/*
* Projection for EventEntity
*/
public interface Event {
Long getId();
String getName();
List<Attendee> getAttendees();
}
В одной из служб, которые мы получаем UserEvent
. Здесь, скажем, мы хотим удалить имена всех пользователей младше 18 и по-прежнему возвращать userEvent
мы только что получили.
public Event getEvent(Long id, Boolean anonymize) {
Event event = this.eventRepository.findById(id);
// The "anonymize" is to highlight that I cannot
// simply solve this in a User-projection
if (!anonymize) {
return event;
}
event
.getAttendees();
.stream()
.peek(attendee -> {
User user = attendee.getUser();
if(user.getAge() < 18) {
// Here we create a new user object without a name
User newUser = new User() {
@Override
String getDisplayName() { return null; }
@Override
Integer getAge() { return user.getAge(); }
}
// !! This is where we hit the problem since we cannot
// !! replace the old user object like this
attendee.setUser(newUser);
}
});
return event;
}