You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Micronaut Data自动序列化Java对象到Postgres varchar列?

如何在Micronaut Data(无Hibernate依赖)中自动序列化Java对象到Postgres的单个VARCHAR/TEXT列

问题场景

你需要将自定义Java对象(如Address)自动序列化/反序列化到Postgres的varchar列,仅使用Micronaut Data(不依赖Hibernate),避免手动用ObjectMapper处理转换。现有代码结构如下:

SQL表定义

CREATE TABLE person (
    id int not null primary key,
    name varchar not null,
    address varchar not null
);

Java实体类

@MappedEntity
public class Person {
    @Id
    private Long id;
    private String name;
    private Address address;

    // getters and setters
}

Address类

public class Address {
    private String street;
    private String city;
    private String streetNumber;

    // getters and setters
}

Repository接口

@Repository
public interface PersonRepository extends CrudRepository<Person, Long> {
}

使用@Serdeable或@JsonProperty注解后仍报错:

Unexpected error in XYZ project: Error executing PERSIST: Unable to set PreparedStatement value: Can't infer the SQL type to use for an instance of x.y.z.Address. Use setObject() with an explicit Types value to specify the type to use.

解决方案

可以通过Micronaut Data的@TypeDef注解配合自定义PropertyConverter实现自动转换,无需手动在业务代码中处理序列化逻辑。

步骤1:实现自定义类型转换器

创建PropertyConverter实现类,利用Micronaut内置的ObjectMapper完成Address与JSON字符串的双向转换:

import io.micronaut.core.convert.ConversionContext;
import io.micronaut.data.model.convert.PropertyConverter;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.inject.Singleton;
import java.util.Optional;

@Singleton
public class AddressConverter implements PropertyConverter<Address, String> {

    private final ObjectMapper objectMapper;

    // 注入Micronaut自带的ObjectMapper,无需手动实例化
    public AddressConverter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public Optional<String> convertToPersistedValue(Address address, ConversionContext context) {
        try {
            return Optional.of(objectMapper.writeValueAsString(address));
        } catch (Exception e) {
            return Optional.empty();
        }
    }

    @Override
    public Optional<Address> convertToEntityValue(String value, ConversionContext context) {
        try {
            return Optional.of(objectMapper.readValue(value, Address.class));
        } catch (Exception e) {
            return Optional.empty();
        }
    }
}

步骤2:在实体类字段上指定类型转换器

修改Person类的address字段,添加@TypeDef注解关联自定义转换器:

import io.micronaut.data.model.DataType;
import io.micronaut.data.model.annotations.TypeDef;
import io.micronaut.data.model.annotations.MappedEntity;
import io.micronaut.data.model.annotations.Id;

@MappedEntity
public class Person {
    @Id
    private Long id;
    private String name;
    // 指定SQL类型为STRING,并关联自定义转换器
    @TypeDef(type = DataType.STRING, converter = AddressConverter.class)
    private Address address;

    // getters and setters
}

说明

  • 此方案无需将address字段改为String类型,Micronaut Data会自动在CRUD操作时调用转换器完成序列化/反序列化。
  • 转换器中使用的是Micronaut内置的ObjectMapper,无需手动创建或维护额外的转换类。
  • Address类只需保持标准的JavaBean结构(具备getter/setter)即可被Jackson正常序列化,若需要更精细的序列化控制,可添加Jackson相关注解(如@JsonProperty)。

内容的提问来源于stack exchange,提问作者Braintertainer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:06:32