JPA-attributkonvertere

1. Introduktion

I denne hurtige artikel dækker vi brugen af ​​de attributkonvertere, der er tilgængelige i JPA 2.1 - som ganske enkelt giver os mulighed for at kortlægge JDBC-typer til Java-klasser.

Vi bruger Hibernate 5 som vores JPA-implementering her.

2. Oprettelse af en konverter

Vi skal vise, hvordan vi implementerer en attributkonverter til en brugerdefineret Java-klasse.

Lad os først oprette en Personnavn klasse - der konverteres senere:

offentlig klasse PersonName implementerer Serialiserbar {privat strengnavn; privat streng efternavn; // getters og setters}

Derefter tilføjer vi en attribut af typen Personnavn til en @Enhed klasse:

@Entity (name = "PersonTable") offentlig klasse person {privat personnavn personnavn; // ...}

Nu skal vi oprette en konverter, der transformerer Personnavn attribut til en databasesøjle og omvendt. I vores tilfælde konverterer vi attributten til en Snor værdi, der indeholder både navn og efternavn felter.

For at gøre det vi er nødt til at kommentere vores konvertererklasse med @Konverter og implementere AttributeConverter interface. Vi parametrerer grænsefladen med typerne af klassen og databasekolonnen i den rækkefølge:

@Converter offentlig klasse PersonNameConverter implementerer AttributeConverter {privat statisk endelig streng SEPARATOR = ","; @ Override public String convertToDatabaseColumn (PersonName personName) {if (personName == null) {return null; } StringBuilder sb = ny StringBuilder (); if (personName.getSname ()! = null &&! personName.getSname () .isEmpty ()) {sb.append (personName.getSname ()); sb.append (SEPARATOR); } hvis (personnavn.getnavn ()! = null &&! personnavn.getnavn (). er tomt ()) {sb.append (personnavn.getnavn ()); } returner sb.toString (); } @ Override public PersonName convertToEntityAttribute (String dbPersonName) {if (dbPersonName == null || dbPersonName.isEmpty ()) {return null; } Streng [] stykker = dbPersonName.split (SEPARATOR); if (pieces == null || pieces.length == 0) {return null; } Personnavn personnavn = nyt personnavn (); Streng firstPiece =! Stykker [0] .isEmpty ()? stykker [0]: null; hvis (dbPersonName.contains (SEPARATOR)) {personName.setSname (firstPiece); if (pieces.length> = 2 && pieces [1]! = null &&! pieces [1] .isEmpty ()) {personName.setName (pieces [1]); }} andet {personName.setName (firstPiece); } returner personnavn; }}

Bemærk, at vi var nødt til at implementere to metoder: convertToDatabaseColumn () og convertToEntityAttribute ().

De to metoder bruges til at konvertere fra attributten til en databasesøjle og omvendt.

3. Brug af konverteren

For at bruge vores konverter skal vi bare tilføje @Konvertere kommentar til attributten, og angiv den konvertererklasse, vi vil bruge:

@Entity (name = "PersonTable") offentlig klasse Person {@Convert (converter = PersonNameConverter.class) privat PersonName personnavn; // ...}

Lad os endelig oprette en enhedstest for at se, at den virkelig fungerer.

For at gøre det gemmer vi først en Person objekt i vores database:

@Test offentligt ugyldigt givenPersonName_whenSaving_thenNameAndSnameConcat () {String name = "name"; String efternavn = "efternavn"; Personnavn personnavn = nyt personnavn (); personnavn.setnavn (navn); personName.setSurname (efternavn); Person person = ny person (); person.setPersonName (personnavn); Lang id = (Lang) session.save (person); session.flush (); session.clear (); }

Dernæst skal vi teste, at Personnavn blev gemt som vi definerede det i konverteren - ved at hente dette felt fra databasetabellen:

@Test offentlig ugyldighed givenPersonName_whenSaving_thenNameAndSnameConcat () {// ... String dbPersonName = (String) session.createNativeQuery ("select p.personName from PersonTable p where p.id =: id") .setParameter ("id", id). getSingleResult (); assertEquals (efternavn + "," + navn, dbPersonnavn); }

Lad os også teste, at konverteringen fra værdien, der er gemt i databasen, til Personnavn klasse fungerer som defineret i konverteren ved at skrive en forespørgsel, der henter hele Person klasse:

@Test offentligt ugyldigt givenPersonName_whenSaving_thenNameAndSnameConcat () {// ... Person dbPerson = session.createNativeQuery ("vælg * fra PersonTable p hvor p.id =: id", Person.class) .setParameter ("id", id) .getSingleResult (); assertEquals (dbPerson.getPersonName () .getName (), navn); assertEquals (dbPerson.getPersonName () .getSname (), efternavn); }

4. Konklusion

I denne korte vejledning viste vi, hvordan man bruger de nyligt introducerede attributkonvertere i JPA 2.1.

Som altid er den fulde kildekode til eksemplerne tilgængelig på GitHub.