使用jOOQ时为PostgreSQL ARRAY列生成List类型
让jOOQ将PostgreSQL ARRAY列生成为List类型的方法
当然可以,有两种常用方式实现这个需求:
1. 自定义数据类型绑定(推荐用于代码生成阶段修改字段类型)
这种方式能直接让jOOQ生成的实体类字段类型变成List<String>,步骤如下:
- 先实现一个
Binding接口,负责数据库数组类型和Java List的双向转换:
public class StringArrayToListBinding implements Binding<Object[], List<String>> { @Override public void get(BindingGetResultSetContext<List<String>> ctx) throws SQLException { String[] dbArray = ctx.resultSet().getArray(ctx.index()).getArray(String[].class); ctx.convert(converter()).value(dbArray != null ? Arrays.asList(dbArray) : null); } @Override public void set(BindingSetStatementContext<List<String>> ctx) throws SQLException { List<String> list = ctx.value(); String[] array = list != null ? list.toArray(new String[0]) : null; ctx.statement().setArray(ctx.index(), ctx.connection().createArrayOf("varchar", array)); } @Override public Converter<Object[], List<String>> converter() { return new Converter<>() { @Override public List<String> from(Object[] dbArray) { return dbArray != null ? Arrays.asList(dbArray) : null; } @Override public Object[] to(List<String> list) { return list != null ? list.toArray(new String[0]) : null; } @Override public Class<Object[]> fromType() { return Object[].class; } @Override public Class<List<String>> toType() { return List.class; } }; } // 实现其他Binding接口的默认方法(如register、sql等,可直接用默认实现) }
- 然后在jOOQ的代码生成配置里指定这个绑定,让它作用到所有varchar[]列:
<database> <customTypes> <customType> <name>java.util.List<String></name> <type>java.util.List</type> <binding>com.your.package.StringArrayToListBinding</binding> </customType> </customTypes> <forcedTypes> <forcedType> <name>java.util.List<String></name> <includeTypes>VARCHAR\\[\\]</includeTypes> <!-- 精确匹配varchar数组类型 --> <!-- 如果要匹配所有数组类型,改成<includeTypes>.*ARRAY</includeTypes> --> </forcedType> </forcedTypes> </database>
重新生成代码后,实体类里对应的ARRAY列就会变成List<String>类型。
2. 运行时全局转换器(适合不想修改代码生成配置的场景)
如果只是希望在查询结果里自动把数组转成List,不需要修改生成的实体类字段类型,可以用jOOQ 3.15+提供的全局转换器配置:
DSLContext dsl = DSL.using( yourPostgresConnection, SQLDialect.POSTGRES, new Settings() .withConverterProvider(new DefaultConverterProvider() { @Override public <T, U> Converter<T, U> provide(Class<T> fromType, Class<U> toType) { if (fromType == String[].class && toType == List.class) { return (Converter<T, U>) new Converter<>() { @Override public List<String> from(String[] array) { return array != null ? Arrays.asList(array) : null; } @Override public String[] to(List<String> list) { return list != null ? list.toArray(new String[0]) : null; } @Override public Class<String[]> fromType() { return String[].class; } @Override public Class<List<String>> toType() { return List.class; } }; } return super.provide(fromType, toType); } }) );
这种方式下,用这个DSLContext查询得到的结果里,数组类型会自动转为List,但生成的实体类字段依然是String[]。
内容的提问来源于stack exchange,提问作者dtech
相关产品推荐
相关产品推荐

