Ich versuche, automatisch eine eindeutige Flugnummer für ein Feld in einer FlightInstance-Entität zu generieren, bevor es in der Datenbank gespeichert wird. Die FlightNumber ist nicht der Primärschlüssel (@Id) und sollte mithilfe einer benutzerdefinierten Sequenzlogik mit einem Präfix generiert werden.
Was ich bisher getan habe
- < li>Es wurde eine benutzerdefinierte Anmerkung erstellt, um das Feld „flightNumber“ zu markieren:
Code: Select all
@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;
}
- Einen benutzerdefinierten Generator implementiert:
Code: Select all
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;
}
}
- Das Feld „flightNumber“ in meiner FlightInstance-Entität mit Anmerkungen versehen:
Code: Select all
@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; }
- Mein Basismodell (FlyWellModel) enthält das @Id-Feld und andere gemeinsame Attribute:
Code: Select all
@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();
}
}
Der benutzerdefinierte FlightNumberSequenceGenerator-Generator wird nicht ausgelöst. Ich habe der Methode „generate()“ Druckanweisungen hinzugefügt, aber bestätigt, dass sie nicht aufgerufen wird. Das Feld „flightNumber“ bleibt nach dem Speichern der Entität in der Datenbank null.
Was ich vermute
Da das Feld „flightNumber“ ist nicht das @Id-Feld, Hibernate verarbeitet den Generator dafür möglicherweise nicht automatisch.
Meine benutzerdefinierte Annotation erfordert möglicherweise eine zusätzliche Konfiguration, um sich in den Entitätslebenszyklus einzubinden.
Was Ich möchte wissen
Wie kann ich Meine benutzerdefinierte Annotation richtig konfigurieren, um die Generatorlogik automatisch auszulösen, bevor die Entität gespeichert wird?
Gibt es eine Einschränkung bei der Verwendung benutzerdefinierter Annotationen oder benutzerdefinierter Generatoren für Felder, die keine Primärschlüssel sind? Was fehlt mir im Setup, damit das funktioniert?