Penukar Atribut JPA

1. Pengenalan

Dalam artikel ringkas ini, kita akan membahas penggunaan Pengubah Atribut yang terdapat di JPA 2.1 - yang, secara sederhana, memungkinkan kita memetakan jenis JDBC ke kelas Java.

Kami akan menggunakan Hibernate 5 sebagai pelaksanaan JPA kami di sini.

2. Membuat Penukar

Kami akan menunjukkan cara melaksanakan penukar atribut untuk kelas Java khusus.

Pertama, mari buat kelas PersonName - yang akan ditukar kemudian:

public class PersonName implements Serializable { private String name; private String surname; // getters and setters }

Kemudian, kami akan menambahkan atribut jenis PersonName ke kelas @Entity :

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

Sekarang kita perlu membuat penukar yang mengubah atribut PersonName ke lajur pangkalan data dan sebaliknya. Dalam kes kami, kami akan menukar atribut ke nilai String yang mengandungi bidang nama dan nama keluarga.

Untuk melakukannya, kita harus memberi penjelasan kepada kelas penukar kita dengan @Converter dan melaksanakan antara muka AttributeConverter . Kami akan membuat parameter antara muka dengan jenis kelas dan lajur pangkalan data, mengikut urutan:

@Converter public class PersonNameConverter implements AttributeConverter { private static final String SEPARATOR = ", "; @Override public String convertToDatabaseColumn(PersonName personName) { if (personName == null) { return null; } StringBuilder sb = new StringBuilder(); if (personName.getSurname() != null && !personName.getSurname() .isEmpty()) { sb.append(personName.getSurname()); sb.append(SEPARATOR); } if (personName.getName() != null && !personName.getName().isEmpty()) { sb.append(personName.getName()); } return sb.toString(); } @Override public PersonName convertToEntityAttribute(String dbPersonName) { if (dbPersonName == null || dbPersonName.isEmpty()) { return null; } String[] pieces = dbPersonName.split(SEPARATOR); if (pieces == null || pieces.length == 0) { return null; } PersonName personName = new PersonName(); String firstPiece = !pieces[0].isEmpty() ? pieces[0] : null; if (dbPersonName.contains(SEPARATOR)) { personName.setSurname(firstPiece); if (pieces.length >= 2 && pieces[1] != null && !pieces[1].isEmpty()) { personName.setName(pieces[1]); } } else { personName.setName(firstPiece); } return personName; } }

Perhatikan bahawa kita harus melaksanakan 2 kaedah: convertToDatabaseColumn () dan convertToEntityAttribute ().

Kedua kaedah digunakan untuk menukar dari atribut ke lajur pangkalan data dan sebaliknya.

3. Menggunakan Penukar

Untuk menggunakan penukar kami, kami hanya perlu menambahkan anotasi @Convert ke atribut dan menentukan kelas penukar yang ingin kami gunakan :

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

Akhirnya, mari buat ujian unit untuk melihat bahawa ia benar-benar berfungsi.

Untuk melakukannya, pertama-tama kami akan menyimpan objek Person dalam pangkalan data kami:

@Test public void givenPersonName_whenSaving_thenNameAndSurnameConcat() { String name = "name"; String surname = "surname"; PersonName personName = new PersonName(); personName.setName(name); personName.setSurname(surname); Person person = new Person(); person.setPersonName(personName); Long id = (Long) session.save(person); session.flush(); session.clear(); }

Seterusnya, kami akan menguji bahawa PersonName disimpan seperti yang kami tetapkan dalam penukar - dengan mengambil medan itu dari jadual pangkalan data:

@Test public void givenPersonName_whenSaving_thenNameAndSurnameConcat() { // ... String dbPersonName = (String) session.createNativeQuery( "select p.personName from PersonTable p where p.id = :id") .setParameter("id", id) .getSingleResult(); assertEquals(surname + ", " + name, dbPersonName); }

Mari kita juga menguji bahawa penukaran dari nilai yang disimpan dalam pangkalan data ke kelas PersonName berfungsi seperti yang ditentukan dalam penukar dengan menulis pertanyaan yang mengambil keseluruhan kelas Orang :

@Test public void givenPersonName_whenSaving_thenNameAndSurnameConcat() { // ... Person dbPerson = session.createNativeQuery( "select * from PersonTable p where p.id = :id", Person.class) .setParameter("id", id) .getSingleResult(); assertEquals(dbPerson.getPersonName() .getName(), name); assertEquals(dbPerson.getPersonName() .getSurname(), surname); }

4. Kesimpulan

Dalam tutorial ringkas ini, kami menunjukkan cara menggunakan Penukar Atribut yang baru diperkenalkan di JPA 2.1.

Seperti biasa, kod sumber penuh untuk contoh boleh didapati di GitHub.