En oversikt over identifikatorer i dvalemodus / JPA

1. Introduksjon

Identifikatorer i dvalemodus representerer den primære nøkkelen til en enhet. Dette innebærer at verdiene er unike slik at de kan identifisere en bestemt enhet, at de ikke er null og at de ikke vil bli endret.

Dvalemodus gir noen forskjellige måter å definere identifikatorer på. I denne artikkelen vil vi gjennomgå hver metode for å kartlegge enhets-ID-er ved hjelp av biblioteket.

2. Enkle identifikatorer

Den enkleste måten å definere en identifikator på er å bruke @Id kommentar.

Enkle ID-er blir kartlagt ved hjelp av @Id til en enkelt egenskap av en av disse typene: Java primitive og primitive wrapper typer, String, Date, BigDecimal, BigInteger.

La oss se et raskt eksempel på å definere en enhet med en primærnøkkel av typen lang:

@Entity offentlig klasse Student {@Id privat lang studentId; // standard konstruktør, getters, setters}

3. Genererte identifikatorer

Hvis vi vil at den viktigste nøkkelverdien skal genereres automatisk for oss, vi kan legge til @GeneratedValue kommentar.

Dette kan bruke fire generasjonstyper: AUTO, IDENTITET, SEKVENS, TABELL.

Hvis vi ikke spesifiserer en verdi eksplisitt, er generasjonstypen som standard AUTO.

3.1. AUTO Generasjon

Hvis vi bruker standard generasjonstype, vil utholdenhetsleverandøren bestemme verdiene basert på typen primærnøkkelattributt. Denne typen kan være numerisk eller UUID.

For numeriske verdier er generasjonen basert på en sekvens eller tabellgenerator, mens UUID verdier vil bruke UUIDGenerator.

La oss se et eksempel på å kartlegge en enhets primærnøkkel ved hjelp av AUTO-genereringsstrategi:

@Entity offentlig klasse Student {@Id @GeneratedValue privat lang studentId; // ...}

I dette tilfellet vil de primære nøkkelverdiene være unike på databasenivå.

En interessant funksjon introdusert i dvalemodus 5 er UUIDGenerator. For å bruke dette, er alt vi trenger å gjøre å erklære en type ID UUID med @GeneratedValue kommentar:

@Entity public class Course {@Id @GeneratedValue private UUID courseId; // ...}

Dvalemodus genererer en id med skjemaet “8dd5f315-9788-4d00-87bb-10eed9eff566”.

3.2. IDENTITET Generasjon

Denne typen generasjon er avhengig av IdentityGenerator som forventer verdier generert av en identitet kolonnen i databasen, noe som betyr at de automatisk økes.

For å bruke denne generasjonstypen trenger vi bare å stille inn strategi parameter:

@Entity offentlig klasse Student {@Id @GeneratedValue (strategi = GenerationType.IDENTITY) privat lang studentId; // ...}

En ting å merke seg er at IDENTITY generasjon deaktiverer batchoppdateringer.

3.3. SEKVENS Generasjon

For å bruke en sekvensbasert ID, gir Hibernate den SequenceStyleGenerator klasse.

Denne generatoren bruker sekvenser hvis de støttes av databasen vår, og bytter til generering av tabeller hvis de ikke er det.

For å tilpasse sekvensnavnet kan vi bruke @GenericGenerator kommentar med SequenceStyleGenerator-strategi:

@Entity offentlig klasse bruker {@Id @GeneratedValue (generator = "sekvensgenerator") @GenericGenerator (navn = "sekvensgenerator", strategi = "org.hibernate.id.enhanced.SequenceStyleGenerator", parametere = {@Parameter ( name = "sequence_name", value = "user_sequence"), @Parameter (name = "initial_value", value = "4"), @Parameter (name = "increment_size", value = "1")}) private long userId; // ...}

I dette eksemplet har vi også satt en startverdi for sekvensen, noe som betyr at generasjonen av primærnøkkelen starter kl.

SEKVENS er generasjonstypen som anbefales i dvale-dokumentasjonen.

De genererte verdiene er unike per sekvens. Hvis du ikke angir et sekvensnavn, vil dvalemodus bruke det samme på nytt dvale_sekvens for forskjellige typer.

3.4. TABELL Generasjon

De TableGenerator bruker en underliggende databasetabell som inneholder segmenter av verdier for generering av identifikatorer.

La oss tilpasse tabellnavnet ved hjelp av @TableGenerator kommentar:

@Entity public class Department {@Id @GeneratedValue (strategy = GenerationType.TABLE, generator = "table-generator") @TableGenerator (name = "table-generator", table = "dep_ids", pkColumnName = "seq_id", valueColumnName = "seq_value") private long depId; // ...}

I dette eksemplet kan vi se at andre attributter som pkColumnName og valueColumnName kan også tilpasses.

Ulempen med denne metoden er at den ikke skalerer godt og kan påvirke ytelsen negativt.

For å oppsummere vil disse fire generasjonstypene resultere i at lignende verdier blir generert, men bruker forskjellige databasemekanismer.

3.5. Egendefinert generator

Hvis vi ikke vil bruke noen av strategiene utenom boksen, vi kan definere vår tilpassede generator ved å implementere IdentifierGenerator grensesnitt.

La oss lage en generator som bygger identifikatorer som inneholder en String prefiks og et tall:

offentlig klasse MyGenerator implementerer IdentifierGenerator, konfigurerbar {privat streng prefiks; @Override offentlig Serializable generere (SharedSessionContractImplementor økt, Objekt obj) kaster HibernateException {String spørring = String.format ("velg% s fra% s", session.getEntityPersister (obj.getClass (). GetName (), obj) .getIdentifierPropertyName ( ), obj.getClass (). getSimpleName ()); Stream ids = session.createQuery (spørring) .stream (); Lang maks = ids.map (o -> o.replace (prefiks + "-", "")) .mapToLong (Long :: parseLong) .max () .orElse (0L); returprefiks + "-" + (maks + 1); } @ Override public void configure (Type type, Properties Properties, ServiceRegistry serviceRegistry) kaster MappingException {prefix = properties.getProperty ("prefix"); }}

I dette eksemplet, vi overstyrer generere() metoden fra IdentifierGenerator grensesnitt og finn først det høyeste tallet fra skjemaets eksisterende primærnøkler prefiks-XX.

Deretter legger vi 1 til det maksimale antallet funnet og legger til prefiks eiendom for å få den nylig genererte ID-verdien.

Vår klasse implementerer også Konfigurerbar grensesnitt, slik at vi kan stille inn prefiks eiendomsverdi i konfigurer () metode.

La oss deretter legge til denne egendefinerte generatoren til en enhet. For dette, vi kan bruke @GenericGenerator kommentar med en strategi parameter som inneholder hele klassenavnet til generatorklassen vår:

@Entity offentlig klasse Produkt {@Id @GeneratedValue (generator = "prod-generator") @ GenericGenerator (name = "prod-generator", parameters = @Parameter (name = "prefix", value = "prod"), strategi = "com.baeldung.hibernate.pojo.generator.MyGenerator") privat strengprodusert; // ...}

Legg også merke til at vi har satt prefiksparameteren til "prod".

La oss se en rask JUnit-test for en klarere forståelse av ID-verdiene som genereres:

@Test offentlig ugyldig nårSaveCustomGeneratedId_thenOk () {Produktprodukt = nytt produkt (); session.save (produkt); Produkt produkt2 = nytt produkt (); session.save (product2); assertThat (product2.getProdId ()). er EqualTo ("prod-2"); }

Her var den første verdien som ble generert ved hjelp av "prod" -prefikset "prod-1", etterfulgt av "prod-2".

4. Sammensatte identifikatorer

I tillegg til de enkle identifikatorene vi har sett så langt, lar Hibernate oss også definere sammensatte identifikatorer.

En sammensatt id er representert av en primærnøkkelklasse med en eller flere vedvarende attributter.

Primærnøkkelklassen må oppfylle flere betingelser:

  • det bør defineres ved hjelp av @EmbeddedId eller @IdClass kommentarer
  • den skal være offentlig, serieiserbar og ha en offentlig ikke-arg konstruktør
  • det skal implementeres er lik() og hashCode () metoder

Klassens attributter kan være grunnleggende, sammensatte eller ManyToOne mens man unngår samlinger og OneToOne attributter.

4.1. @EmbeddedId

Å definere en id ved hjelp av @EmbeddedId, først trenger vi en primærnøkkelklasse merket med @Embeddable:

@Embeddable public class OrderEntryPK implementerer Serializable {private long orderId; privat langt produktId; // standard konstruktør, getters, setter // er lik () og hashCode ()}

Deretter kan vi legge til en ID av typen OrderEntryPK til en enhet som bruker @EmbeddedId:

@Entity offentlig klasse OrderEntry {@EmbeddedId privat OrderEntryPK entryId; // ...}

La oss se hvordan vi kan bruke denne typen sammensatt id til å angi primærnøkkelen for en enhet:

@Test offentlig ugyldig nårSaveCompositeIdEntity_thenOk () {OrderEntryPK entryPK = new OrderEntryPK (); entryPK.setOrderId (1L); entryPK.setProductId (30L); OrderEntry entry = new OrderEntry (); entry.setEntryId (entryPK); session.save (oppføring); assertThat (entry.getEntryId (). getOrderId ()). isEqualTo (1L); }

Her er OrderEntry objektet har et OrderEntryPK primær id dannet av to attributter: Bestillings ID og Produkt ID.

4.2. @IdClass

De @IdClass merknader ligner på @EmbeddedId, unntatt attributtene er definert i hovedenhetsklassen ved hjelp av @Id for hver eneste.

Primærnøkkelklassen vil se ut som før.

La oss skrive om OrderEntry eksempel med en @IdClass:

@Entity @IdClass (OrderEntryPK.class) offentlig klasse OrderEntry {@Id privat lang orderId; @Id privat langt produktId; // ...}

Da kan vi sette id-verdiene direkte på OrderEntry gjenstand:

@Test offentlig ugyldig nårSaveIdClassEntity_thenOk () {OrderEntry entry = new OrderEntry (); entry.setOrderId (1L); entry.setProductId (30L); session.save (oppføring); assertThat (entry.getOrderId ()). er EqualTo (1L); }

Merk at den primære nøkkelklassen for begge typer sammensatte ID-er kan også inneholde @ManyToOne attributter.

Dvalemodus tillater også å definere primærnøkler som består av @ManyToOne foreninger kombinert med @Id kommentar. I dette tilfellet bør enhetsklassen også oppfylle vilkårene for en primærnøkkelklasse.

Ulempen med denne metoden er at det ikke er noen skille mellom enhetsobjektet og identifikatoren.

5. Avledede identifikatorer

Avledede identifikatorer er hentet fra en enhets forening ved hjelp av @MapsId kommentar.

La oss først lage en Brukerprofil enhet som henter sitt ID fra en en-til-en tilknytning til Bruker enhet:

@Entity offentlig klasse UserProfile {@Id privat lang profileId; @OneToOne @MapsId privat brukerbruker; // ...}

La oss deretter bekrefte at a Brukerprofil forekomst har samme ID som tilknyttet Bruker forekomst:

@Test offentlig ugyldig nårSaveDerivedIdEntity_thenOk () {Brukerbruker = ny bruker (); session.save (bruker); UserProfile-profil = ny UserProfile (); profile.setUser (bruker); session.save (profil); assertThat (profile.getProfileId ()). er EqualTo (user.getUserId ()); }

6. Konklusjon

I denne artikkelen har vi sett flere måter vi kan definere identifikatorer på i dvalemodus.

Den fulle kildekoden til eksemplene finner du på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found