Статьи

Включите вашу модель данных с помощью прогнозов

Вступление

Модели данных могут быть хитрыми. Моделирование может быть еще сложнее. Иногда информация, которая должна попадать в таблицу базы данных, не обязательно является тем, что мы хотим передать каждому фрагменту кода.

И, как и во многих других случаях, Весна приходит на помощь. Небольшая функция, называемая проекцией, помогает нам отображать данные с помощью нескольких строк в обычном интерфейсе.

В этой статье мы рассмотрим простой пример того, как мы можем использовать проекции.

Основы

Хорошо, давайте установим сцену. Представьте, что у нас есть следующая сущность:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table
@EqualsAndHashCode(doNotUseGetters = true)
@ToString(doNotUseGetters = true)
public class User implements Serializable {
  
 @Id
 @SequenceGenerator(name = "user_seq", sequenceName = "user_seq")
 @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "user_seq")
 private Long id;
  
 @Basic
 private String username;
  
 @Basic
 private String salt;
  
 @Basic
 private String password;
  
 @Basic
 private String firstName;
  
 @Basic
 private String lastName;
}

Некоторое объяснение может быть полезным здесь: Давайте посмотрим на аннотации. Честно говоря, я ленив, поэтому Ломбок прямо в моем переулке. Lombok дает нам хороший декларативный способ сказать, что нам нужно:

  • хороший интерфейс для создания компонента ( @Builder )
  • Геттеры и @Data ( @Data )
  • конструктор по умолчанию ( @NoArgsConstructor )
  • еще один конструктор с аргументами для всех полей ( @AllArgsConstructor )
  • equals() и hashCode() , но, пожалуйста, используйте поля, а не получатели ( @EqualsAndHashCode(doNotUseGetters = true) )
  • toString() ; снова используйте поля ( @ToString(doNotUseGetter = true) )

Остальные аннотации ( @Entity и @Table ) — старые добрые JPA.

Итак, у нас есть хорошая сущность. В чем проблема?

Получить данные традиционным способом

Давайте посмотрим на этот репозиторий:

1
2
3
4
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
 
}

Приведенный выше код предоставляет нам минимальный набор методов CRUD. Одним из них является getOne(Long id) . Хорошо не правда ли?

Ну, правильный ответ должен быть: это зависит! Почему? Потому что это возвращает всю сущность, включая соль и хешированный пароль. Это очень конфиденциальная информация. Особенно соль никогда не должна быть доступна для внешнего мира.

Чтобы получить эту информацию из полученной сущности, нам пришлось бы проделать много ручной работы. От всей души нам нужно: * создать новый компонент * реализовать средство отображения для перехода от нашей сущности к новому компоненту * убедиться, что каждый раз, когда мы имеем дело с этим объектом, мы также отображаем его * получая головные боли при реализации этого Также возможны несколько результатов.

Возврат необходимого минимума

К счастью, весна в день. Небольшая функция под названием « Проекции» позволяет нам определять отображение декларативным способом. Такой интерфейс может выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
public interface UserProjection {
  
 @Value("#{target.getUsername()}")
 String getUsername();
  
 @Value("#{target.getFirstName()}")
 String getFirstName();
  
 @Value("#{target.getLastName()}")
 String getLastName();
}

Spring заменит target на объект, с которым мы сейчас имеем дело. Другими словами, target будет экземпляром User .

Единственное, что нам нужно сделать сейчас, это что-то вроде этого:

1
2
3
4
5
6
7
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
  
 UserProjection findById(Long id);
  
 List<UserProjection> findAllUser();
}

Теперь каждый раз, когда мы вызываем findById() , мы получим экземпляр UserProjection . Никакая утечка нашей соли или пароля не возможна! Более того, мы можем использовать одну и ту же процедуру для методов с несколькими результатами.

Вывод

Мы можем сэкономить много кода и усилий с помощью Spring Projection. И определения @Value() могут быть настолько сложными, насколько нам это нужно. Например, в моем текущем проекте это экономит моей команде много стандартного кода, когда мы отображаем «интересный» унаследованный дизайн базы данных в более простые модели данных.

Если вы хотите попробовать это, вы можете найти простой пример приложения на GitHub .

Опубликовано на Java Code Geeks с разрешения Holger Steinhauer, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Включите вашу модель данных с помощью прогнозов

Мнения, высказанные участниками Java Code Geeks, являются их собственными.