Java >> Java tutorial >  >> Tag >> hibernate

Sådan genereres værdier af grundlæggende enhedsattributter med Hibernate

Hibernate og JPA-specifikationen definerer flere generatorer for at skabe unikke primære nøgleværdier. Et oplagt spørgsmål, når du lærer om disse generatorer, er, om du også kan anvende dem på grundlæggende egenskaber. Desværre er svaret nej.

Men Hibernates ValueGenerator giver et letanvendeligt alternativ. Som jeg vil vise dig i denne artikel, kan du bruge det på alle dine grundlæggende enhedsattributter til at generere deres værdier, før du indsætter eller opdaterer enhedsobjektet.

En eksempelmodel

Før vi ser nærmere på Værdigeneratoren implementering og brugen heraf, vil jeg hurtigt vise dig den domænemodel, vi vil bruge i denne artikel. Den består af en simpel ChessTournament enhed, som implementerer Begivenheden grænseflade.

@Entity
public class ChessTournament implements Event {
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tournament_seq")
    @SequenceGenerator(name = "tournament_seq", sequenceName = "tournament_seq", initialValue = 100)
    private Long id;

    private String name;

    private LocalDate startDate;

    private LocalDate endDate;

    @GeneratorType(type = EventCodeGenerator.class, 
                   when = GenerationTime.INSERT)
    private String tournamentCode;

    @Version
    private int version;

    @ManyToMany
    private Set<ChessPlayer> players = new HashSet<>();

    @OneToMany
    private Set<ChessGame> games = new HashSet<>();

    ...
}

Som du kan se i kodeeksemplet, er ChessTournament enhed bruger en databasesekvens til at generere unikke primære nøgleværdier, 2 associationer til ChessPlayer entitet og de grundlæggende attributter navn , startdato , slutdato, og turneringskode . Vi bruger navnet og startdatoen attributter i vores Value Generator implementering for at generere værdien af ​​turneringskoden attribut.

Begivenheden grænsefladen definerer kun metoderne getName og getStartDate . Den eneste grund til, at jeg inkluderede grænsefladen i dette eksempel, er, at den vil give os en enkel måde at implementere en ValueGenerator på der ikke afhænger af en bestemt enhedsklasse.

public interface Event {
    
    public String getName();

    public LocalDate getStartDate();
}

Implementer en tilpasset generator

Implementeringen af ​​en brugerdefineret generator er ligetil. Du skal implementere ValueGenerator grænseflade, som kun definerer metoden T genererValue(sessionssession, objektejer) . Inden for denne metode kan du få adgang til den aktuelle dvaletilstand session og entitetsobjektet, som generatoren anvendes på, med alle dets attributværdier.

Og før du spørger, implementerer Hibernates primære nøglegeneratorer desværre ikke denne grænseflade og kan ikke bruges som en ValueGenerator .

Lad os implementere en Value Generator der genererer koden til en Begivenhed .

public class EventCodeGenerator implements ValueGenerator<String> {

    Logger log = Logger.getLogger(EventCodeGenerator.class.getSimpleName());

    @Override
    public String generateValue(Session session, Object owner) {
        Event event = (Event) owner;
        String code = event.getName().replace(" ", "")
                        +"-"+event.getStartDate().getMonth().getValue()
                        +"-"+event.getStartDate().getYear();
        log.info("Generated event code: "+code);
        return code;
    }
    
}

I dette simple eksempel bruger jeg Begivenheden 's navn og dets startdato for at generere koden. Når vi tildeler denne generator til en entity-attribut, vil Hibernate tildele værdien, der returneres af denne metode, til attributten, før den fortsætter eller opdaterer den.

Brug en generator i din kortlægning

Efter at have defineret generatoren, kan du bruge den med enhver enhedsattribut af en matchende type. I eksemplet med denne artikel vil jeg anvende det på turneringskoden attribut for ChessTournament enhedsklasse.

Du kan anvende en generator til en enhedsattribut ved at annotere den med @GeneratorType og at henvise til implementeringsklassen som typeattributten. Værdien af ​​den valgfrie når attribut definerer, hvornår Hibernate skal anvende generatoren. Du kan vælge mellem INSERT , ALTID , og ALDRIG .

@Entity
public class ChessTournament implements Event {

    @GeneratorType(type = EventCodeGenerator.class, 
                   when = GenerationTime.INSERT)
    private String tournamentCode;
    
    ...
}

Når du har anvendt annoteringen, kalder Hibernate generateValue metoden for den refererede ValueGenerator afhængigt af den angivne GenerationTime enum værdi.

Du kan se det i log-outputtet, når jeg fortsætter med en ny ChessTournament enhed. Hibernate kaldet EventCodeGenerator og indstil den returnerede værdi som værdien af ​​turneringskoden attribut.

18:08:05,323 DEBUG SQL:144 - select nextval ('tournament_seq')
18:08:05,334 DEBUG SQL:144 - select nextval ('tournament_seq')
Aug. 30, 2021 6:08:05 PM com.thorben.janssen.sample.model.EventCodeGenerator generateValue
INFO: Generated event code: MyTournament-8-2021
18:08:05,376 DEBUG SQL:144 - insert into ChessTournament (endDate, name, startDate, tournamentCode, version, id) values (?, ?, ?, ?, ?, ?)
18:08:05,380 TRACE BasicBinder:52 - binding parameter [1] as [DATE] - [null]
18:08:05,381 TRACE BasicBinder:64 - binding parameter [2] as [VARCHAR] - [My Tournament]
18:08:05,382 TRACE BasicBinder:64 - binding parameter [3] as [DATE] - [2021-08-01]
18:08:05,384 TRACE BasicBinder:64 - binding parameter [4] as [VARCHAR] - [MyTournament-8-2021]
18:08:05,384 TRACE BasicBinder:64 - binding parameter [5] as [INTEGER] - [0]
18:08:05,386 TRACE BasicBinder:64 - binding parameter [6] as [BIGINT] - [100]

Konklusion

Ved at implementere Hibernates ValueGenerator grænseflade, kan du generere værdierne af grundlæggende enhedsattributter. Som jeg viste dig i denne artikel, implementeringen af ​​ValueGenerator er ligetil og kræver normalt kun nogle få linjer kode.

Når du har implementeret generatoren, kan du tildele den til en entity-attribut ved at annotere den med @GeneratorType og refererer til din generatorimplementering.


Java tag