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で利用可能]です。