JPA Attribute Converters

1. Introduksjon

I denne raske artikkelen vil vi dekke bruken av attributtomformere som er tilgjengelige i JPA 2.1 - som enkelt sagt lar oss kartlegge JDBC-typer til Java-klasser.

Vi bruker Hibernate 5 som vår JPA-implementering her.

2. Opprette en omformer

Vi skal vise hvordan du implementerer en attributtomformer for en tilpasset Java-klasse.

La oss først lage en Personnavn klasse - som blir konvertert senere:

public class PersonName implementerer Serializable {private String name; privat streng etternavn; // getters og setters}

Deretter legger vi til et attributt av typen Personnavn til en @Enhet klasse:

@Entity (name = "PersonTable") offentlig klasse Person {private PersonName personName; // ...}

Nå må vi lage en omformer som transformerer Personnavn attributt til en databasekolonne og omvendt. I vårt tilfelle konverterer vi attributtet til a String verdi som inneholder både navn og etternavn felt.

Å gjøre slik vi må legge merke til omformerklassen vår med @Konverterer og implementere AttributeConverter grensesnitt. Vi parametriserer grensesnittet med typene av klassen og databasekolonnen, i den rekkefølgen:

@Converter public class PersonNameConverter implementerer AttributeConverter {privat statisk sluttstreng 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 = nytt personnavn (); Streng firstPiece =! Brikker [0] .isEmpty ()? brikker [0]: null; hvis (dbPersonName.contains (SEPARATOR)) {personName.setSname (firstPiece); if (pieces.length> = 2 && pieces [1]! = null &&! pieces [1] .isEmpty ()) {personName.setName (pieces [1]); }} annet {personName.setName (firstPiece); } returner personnavn; }}

Legg merke til at vi måtte implementere to metoder: convertToDatabaseColumn () og convertToEntityAttribute ().

De to metodene brukes til å konvertere fra attributtet til en databasekolonne og omvendt.

3. Bruke Converter

For å bruke omformeren vår, trenger vi bare å legge til @Konvertere kommentar til attributtet og spesifiser omformerklassen vi vil bruke:

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

Til slutt, la oss lage en enhetstest for å se at den virkelig fungerer.

For å gjøre det lagrer vi først en Person objekt i databasen vår:

@Test offentlig ugyldig givenPersonName_whenSaving_thenNameAndSnameConcat () {String name = "name"; String etternavn = "etternavn"; Personnavn personnavn = nytt personnavn (); personnavn.settnavn (navn); personName.setSurname (etternavn); Personperson = ny person (); person.setPersonName (personName); Lang id = (Lang) økt. Lagre (person); session.flush (); session.clear (); }

Deretter skal vi teste at Personnavn ble lagret slik vi definerte det i omformeren - ved å hente det feltet fra databasetabellen:

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

La oss også teste at konverteringen fra verdien som er lagret i databasen til Personnavn klasse fungerer som definert i omformeren ved å skrive et spørsmål som henter hele Person klasse:

@Test offentlig ugyldighet gittPersonName_whenSaving_thenNameAndSnameConcat () {// ... Person dbPerson = session.createNativeQuery ("velg * fra PersonTable p hvor p.id =: id", Person.class) .setParameter ("id", id) .getSingleResult (); assertEquals (dbPerson.getPersonName () .getName (), navn); assertEquals (dbPerson.getPersonName () .getSname (), etternavn); }

4. Konklusjon

I denne korte opplæringen viste vi hvordan du bruker de nylig introduserte attributtomformerne i JPA 2.1.

Som alltid er hele kildekoden for eksemplene tilgjengelig på GitHub.