Я пытаюсь автоматически сгенерировать уникальный номер FlightNumber для поля в сущности FlightInstance перед его сохранением в базе данных. FlightNumber не является первичным ключом (@Id) и должен генерироваться с использованием пользовательской логики последовательности с префиксом.
Что я уже сделал
- < li>Создана специальная аннотация для обозначения поля FlightNumber:
Код: Выделить всё
@IdGeneratorType(value = FlightNumberSequenceGenerator.class)
@Retention(RUNTIME)
@Target({METHOD,FIELD})
public @interface FlightNumberSequence {
String name();
String prefix() default "FWF-";
int startWith() default 1;
int incrementBy() default 1;
}
- Реализован собственный генератор:
Код: Выделить всё
public class FlightNumberSequenceGenerator implements BeforeExecutionGenerator {
private final String prefix;
private final int incrementBy;
public FlightNumberSequenceGenerator(FlightNumberSequence config) {
System.out.println("Hello from FlightNumberSequenceGenerator");
this.prefix = config.prefix();
this.incrementBy = config.incrementBy();
}
@Override
public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) {
System.out.println("Hello from FlightNumberSequenceGenerator");
return session.doReturningWork(connection -> {
try (Statement statement = connection.createStatement()) {
ResultSet resultSet = statement.executeQuery("SELECT next_val FROM flight_number_sequence FOR UPDATE");
if (resultSet.next()) {
int nextVal = resultSet.getInt("next_val");
statement.executeUpdate("UPDATE flight_number_sequence SET next_val = " + (nextVal + incrementBy));
return prefix + nextVal;
} else {
throw new IdentifierGenerationException("Unable to fetch the next sequence value.");
}
} catch (Exception e) {
throw new IdentifierGenerationException("Error generating flight number.", e);
}
});
}
@Override
public EnumSet getEventTypes() {
return EventTypeSets.INSERT_ONLY;
}
}
- Добавил примечание к полю FlightNumber в моем объекте FlightInstance:
Код: Выделить всё
@Entity @Getter @Setter @ToString @AllArgsConstructor @NoArgsConstructor public class FlightInstance extends FlyWellModel { private boolean isFullyBooked; @Column(unique = true) @FlightNumberSequence(name = "flight_number_sequence", startWith = 1000, incrementBy = 3) private String flightNumber; private LocalDateTime departureTime; private LocalDateTime arrivalTime; private int baggageAllowance; @OneToOne private AirCraft airCraft; @OneToOne @ToString.Exclude private Flight flight; @Enumerated(STRING) private FlightStatus status; @OneToMany() @ToString.Exclude private List flightSeat; } - Моя базовая модель (FlyWellModel) включает поле @Id и другие общие атрибуты:
Код: Выделить всё
@Getter
@Setter
@SuperBuilder
@EntityListeners(value = {AuditingEntityListener.class})
@MappedSuperclass
@NoArgsConstructor
@AllArgsConstructor
public class FlyWellModel {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
private String publicId;
@CreatedDate
LocalDateTime createdDate;
@LastModifiedDate
LocalDateTime lastModifiedDate;
@CreatedBy
@Builder.Default
String createdBy = "SYSTEM";
String createdByRole;
@LastModifiedBy
String lastModifiedBy;
@PrePersist
private void generatePublicId(){
publicId = UUID.randomUUID().toString();
}
}
Пользовательский генератор FlightNumberSequenceGenerator не запускается. Я добавил операторы печати в методgenerate(), но подтвердил, что он не вызывается. Поле FlightNumber остается нулевым после сохранения объекта в базе данных.
Что я подозреваю
Поскольку поле FlightNumber имеет значение а не поле @Id, Hibernate может не обрабатывать его генератор автоматически.
Моя пользовательская аннотация может потребовать дополнительной настройки для подключения к жизненному циклу объекта.
Что Я хочу знать
Как правильно настроить пользовательскую аннотацию для автоматического запуска логики генератора перед сохранением объекта?
Существует ли ограничение на использование пользовательских аннотаций или пользовательских генераторов для полей, которые не являются первичными ключами? Чего мне не хватает в настройке, чтобы это работало?
Подробнее здесь: https://stackoverflow.com/questions/793 ... -boot-appl
Мобильная версия