红茶的个人站点

  • 首页
  • 专栏
  • 开发工具
  • 其它
  • 隐私政策
Awalon
Talk is cheap,show me the code.
  1. 首页
  2. 专栏
  3. Spring Boot 学习笔记
  4. 正文

从零开始 Spring Boot 53:JPA 属性转换器

2023年6月30日 1254点热度 0人点赞 0条评论

spring boot

图源:简书 (jianshu.com)

这篇文章介绍如何在 JPA(Hibernate)中使用属性转换器。

在前篇文章中,我介绍了如何使用@Embedded和@Embeddable将一个类型嵌入实体类,并映射表结构中的某几列数据。实际上,在日常开发中,将一些当前表的附加信息单独存储成一个序列化或 JSON 格式的字段是很常见的情况。

下面就演示怎么在 JPA 中这么做。

实体类

首先,看作为示例的实体类:

@AllArgsConstructor
@Builder
@Data
@Entity
@Table(name = "user_student3")
@Accessors(chain = true)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Student3 {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @EqualsAndHashCode.Include
    private Long id;
​
    @Column(length = 25, nullable = false)
    private String name;
​
    @Column(length = 50, nullable = false)
    private String address;
    
    @Column(columnDefinition = "text")
    private Contacts contacts;
​
    public Student3() {
​
    }
}
​
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@EqualsAndHashCode
public class Contacts {
    private String name;
    private String address;
    private String phone;
}

其属性contacts我们不再像之前那样映射到多个字段,而是直接存储到一个字段上,所以这里用@Column(columnDefinition = "text")进行标注。

  • 考虑到通常的 JSON 串长度以及未来的扩展需要,使用 TEXT 作为对应字段的类型是个常见手段。

  • 也可以使用@Lob注解(Large Object)标记属性让其对应的表结构列变成 TEXT 类型,但在数据库是MySQL 的时候,列类型会变成TINY TEXT而非TEXT,前者最大长度是255,因此这么做不太合适。

属性转换器

为了能让 Hibernate 知道怎么处理Contacts类型,我们需要定义一个属性转换器(Attribute Converter),并在转换器中实现具体的转换逻辑:

@Converter
public class ContactsConverter implements AttributeConverter<Contacts, String> {
​
    @Override
    @SneakyThrows
    public String convertToDatabaseColumn(Contacts attribute) {
        ObjectMapper om = new ObjectMapper();
        return om.writeValueAsString(attribute);
    }
​
    @Override
    @SneakyThrows
    public Contacts convertToEntityAttribute(String dbData) {
        if (ObjectUtils.isEmpty(dbData)) {
            return null;
        }
        ObjectMapper om = new ObjectMapper();
        return om.readValue(dbData, Contacts.class);
    }
}

可以看到,Hibernate 的属性转换器需要使用@Converter注解并实现AttributeConverter接口。

转换器中需要实现两个方法,分别对应将具体类型转换为String以及将String还原为具体类型。在这个示例中,我们使用 JSON 作为转换的目标字符串格式,通过 Spring 内置的 FastJSON 可以很容易实现这一点。

使用转换器很简单:

// ...
public class Student3 {
    // ...
    @Convert(converter = ContactsConverter.class)
    @Column(columnDefinition = "text")
    private Contacts contacts;
    // ...
}

在相应属性上使用@Convert注解,并设置具体使用的转换器即可。

测试

测试用例:

@Test
@SneakyThrows
void testAddNewStudent() {
    Student3 newStudent = Student3.builder()
        .address("宁安大街101号")
        .name("icexmoon")
        .contacts(Contacts.builder()
                  .name("lalala")
                  .address("北京东路100号")
                  .phone("123456789")
                  .build())
        .build();
    student3Repository.save(newStudent);
    Assertions.assertNotNull(newStudent.getId());
    var findStudents = student3Repository.findAllById(List.of(newStudent.getId()));
    var findStudent = findStudents.stream().filter(s -> s.getId().equals(newStudent.getId())).findFirst().get();
    Assertions.assertEquals(newStudent.getContacts(), findStudent.getContacts());
}

The End,谢谢阅读。

本文的完整示例代码可以在这里获取。

参考资料

  • JPA Attribute Converters | Baeldung

  • JPA Annotation for the PostgreSQL TEXT Type | Baeldung

  • MySQL text类型 - MySQL教程 (yiibai.com)

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: Converter jpa spring
最后更新:2023年6月30日

魔芋红茶

加一点PHP,加一点Go,加一点Python......

点赞
< 上一篇
下一篇 >

文章评论

取消回复

*

code

COPYRIGHT © 2021 icexmoon.cn. ALL RIGHTS RESERVED.
本网站由提供CDN加速/云存储服务

Theme Kratos Made By Seaton Jiang

宁ICP备2021001508号

宁公网安备64040202000141号