如何用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
相关产品推荐
相关产品推荐

