JPA属性コンバーター

1.はじめに

このクイック記事では、JPA 2.1で使用可能な属性コンバーターの使用法について説明します。これにより、簡単に言えば、JDBCタイプをJavaクラスにマップできます。

ここでは、JPA実装としてHibernate5を使用します。

2.コンバーターの作成

カスタムJavaクラスの属性コンバーターを実装する方法を示します。

まず、PersonNameクラスを作成しましょう–後で変換されます:

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

その後、我々は、タイプの属性追加しますPersonNameのを@Entityのクラス:

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

次に、PersonName属性をデータベース列に(またはその逆に)変換するコンバーターを作成する必要があります。この例では、属性を名前フィールドと姓フィールドの両方を含む文字列値に変換します。

これを行うには、コンバータークラスに@Converterアノテーションを付け、AttributeConverterインターフェイスを実装する必要があります。クラスのタイプとデータベース列を使用して、インターフェイスを次の順序でパラメータ化します。

@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; } }

convertToDatabaseColumn()convertToEntityAttribute()の2つのメソッドを実装する必要があることに注意してください

2つの方法は、属性からデータベース列に、またはその逆に変換するために使用されます。

3.コンバーターの使用

コンバーターを使用するには、属性に@Convertアノテーションを追加し、使用するコンバータークラスを指定する必要があります

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

最後に、単体テストを作成して、実際に機能することを確認しましょう。

そのためには、最初にPersonオブジェクトをデータベースに保存します。

@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(); }

次に、データベーステーブルからそのフィールドを取得することにより、PersonNameがコンバーターで定義したとおりに格納されていることをテストします。

@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); }

また、Personクラス全体を取得するクエリを記述して、データベースに格納されている値からPersonNameクラスへの変換がコンバーターで定義されているとおりに機能することをテストしてみましょう。

@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.結論

この簡単なチュートリアルでは、JPA2.1で新しく導入された属性コンバーターの使用方法を示しました。

いつものように、例の完全なソースコードはGitHubで入手できます。