page contents

浅谈JPA属性转换器

1. 简介在这篇文章中,我们将介绍JPA 2.1中可用的属性转换器的用法 - 简单地说,它允许我们将JDBC类型映射到Java类。我们将在这里使用Hibernate 5作为我们的JPA实现。2.创建转换器我们将展示...


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()。

这两种方法用于从属性转换为数据库列,反之亦然。


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);
}
  • 发表于 2020-01-11 14:05
  • 阅读 ( 557 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

1135 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1478 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章