Аннотация @ColumnDefault надо полем класса предметной области заставит Hibernate создать для этого поля колонку в БД со значением по умолчанию, которое передаёт параметром в эту аннотацию. Кроме того, с помощью параметра GenerationTime.INSERT аннотации @Generated можно определить, возможно ли будет переопределять значение по умолчанию при вставке или оно всегда будет одним и тем же, когда создаётся новая запись в таблице.
Создадим минимальное Spring Boot приложение с поддержкой JPA/Hibernate
Создадим класс предметной области следующего содержания:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@Entity public class Player { @Id @GeneratedValue private Long id; private String name; @ColumnDefault("18") @org.hibernate.annotations.Generated( org.hibernate.annotations.GenerationTime.INSERT ) private Integer age; @Column(insertable = false) @org.hibernate.annotations.ColumnDefault("0") @org.hibernate.annotations.Generated( org.hibernate.annotations.GenerationTime.INSERT ) private Integer score; //Конструкторы, геттеры и сеттеры, equals(), hashCode() и т.д. } |
От данного кода мы ожидаем следующий результат:
Поле age помечено аннотацией @ColumnDefault с параметром value, установленном в «18». А также аннотацией @Generated с параметром value = GenerationTime.INSERT. Мы ожидаем, что при создании схемы БД в таблице PLAYER будет создана колонка age со значением по умолчанию 18. При этом, значение по умолчанию будет устанавливаться только при вставке (не при апдейте) и только если поле age сохраняемого объекта равно null. Если во время вставки в объекте поле age будет заполнено, то значение по умолчанию использовано не будет.
Поле score помечено теми же аннотациями, а также аннотацией @Column с параметром insertable = false. Мы ожидаем, что при вставке значение этого поля в объекте будет проигнорировано, что бы в нём ни было записано. А значит, что новая строка таблицы PLAYER всегда будет содержать «0» в этой колонке.
Создадим репозиторий для нашего класса предметной области:
1 2 3 4 |
@Repository public interface PlayerRepository extends JpaRepository<Player, Long> { Player findFirstByName(String name); } |
Проверим работу аннотаций в следующем тесте:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@SpringBootTest class SpringHibernatePostgresqlApplicationTests { @Autowired PlayerRepository playerRepository; @Test void addNewPersonApi() throws Exception { playerRepository.deleteAll(); Player irina = new Player("Irina"); Player nina = new Player("Nina", 3, 10); playerRepository.saveAll(List.of(irina, nina)); Player irinaInDb = playerRepository.findFirstByName("Irina"); Player ninaInDb = playerRepository.findFirstByName("Nina"); assertEquals(irinaInDb.getAge(),18); assertEquals(irinaInDb.getScore(),0); assertEquals(ninaInDb.getScore(),0); } } |
Мы создаём два объекта класса Player и делаем вставку в БД. ОБъекту irina мы заполняем только поле name, поля age и score должны будут оказаться заполненными значениями по умолчанию.
Объекту nina мы заполним все поля, в том числе score.
Сразу после вставки в БД мы запрашиваем соответствующие строки и смотрим, как они в итоге сохранились.
В ассертах мы видим, что поле age Ирины заполнилось значением по умолчанию 18, а поле score заполнилось значением 0. Собственно этого мы и ожидали от аннотации @ColumnDefault.
Объекту nina мы задали все поля, в том числе задали поле score равное 10. Однако, из-за аннотации @Column с параметром insertable = false, это значение было проигнорировано при вставке и в БД у Нины в колонке SCORE записан 0.
В схеме это выглядит следующим образом:
Значения по умолчанию задаются внутри самой БД. Использовать или отбрасывать значение поля объекта при вставке — решает Hibernate, ориентируясь на параметр insertable аннотации @Column.