JPA属性コンバータ
1前書き
この簡単な記事では、JPA 2.1で使用可能な属性コンバーターの使用法について説明します。つまり、JDBCタイプをJavaクラスにマップすることができます。
ここでは、Hibernate 5をJPA実装として使用します。
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
属性をデータベース列に、およびその逆に変換するコンバーターを作成する必要があります。ここでは、属性をnameフィールドとsurnameフィールドの両方を含む
String
値に変換します。
そのためには、
コンバータークラスに
@ Converter
というアノテーションを付けて
AttributeConverter
インターフェースを実装する必要があります。
インターフェースをクラスとデータベース列の型の順序でパラメーター化します。
@Converter
public class PersonNameConverter implements
AttributeConverter<PersonName, String> {
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;
}
}
-
2つのメソッド、
convertToDatabaseColumn()
と__convertToEntityAttribute()を実装する必要があることに注意してください。
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);
}
データベースに格納されている値から
PersonName
クラスへの変換が、
Person
クラス全体を取得するクエリを作成することによって、コンバーターで定義されているとおりに機能することもテストしましょう。
@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結論
この短いチュートリアルでは、JPA 2.1で新しく導入された属性コンバータの使用方法を示しました。
いつものように、例の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/hibernate5[GitHubで利用可能]です。