当前位置: 首页 > 知识库问答 >
问题:

带POJO转换器的Jooq

上官琦
2023-03-14

我正试图在Jooq的帮助下实现一个软件,将数据读写到h2数据库中。我的PLC_数据表有一个带有时间戳的列,该列通常映射到LocalDateTime,但我需要将该数据映射到POJO中的Instant,因此我编写了自定义转换器:

public class TimestampConverter implements Converter<LocalDateTime, Instant> {

    private static final long serialVersionUID = -2866811348870878385L;

    /**
     * Convert a {@code LocalDateTime} into {@code Instant}
     */
    @Override
    public Instant from(LocalDateTime databaseObject) {
        return databaseObject.toInstant(ZoneOffset.UTC);
    }

    /**
     * Convert a {@code Instant} into {@code Timestamp}
     */
    @Override
    public LocalDateTime to(Instant userObject) {
        return userObject.atZone(ZoneOffset.UTC).toLocalDateTime();
    }

    /**
     * Return the from Type Class
     */
    @Override
    public Class<LocalDateTime> fromType() {
        return LocalDateTime.class;
    }

    /**
     * Return the to Type Class
     */
    @Override
    public Class<Instant> toType() {
        return Instant.class;
    }
}

我在我的build.gradle文件中引用了forcedType:

forcedType {
    userType = 'java.time.Instant'
    converter = 'it.fox.plcwebgui.utils.db.TimestampConverter'                      
    includeTypes = 'TIMESTAMP.*'
}

我已经注释了我的POJO:

public class PlcEventBean implements Serializable {

    private static final long serialVersionUID = 1988924276212981713L;

    @Column(name = "ID")
    public long id = 0;

    @Column(name = "EVENT_INSTANT")
    public Instant eventInstant = Instant.ofEpochMilli(0);

    @Column(name = "MAX_FORCE")
    private int maxForce;

    /**
     * Get the Event ID
     * @param id the id
     */
    public long getId() {
        return id;
    }

    /**
     * Set the Event ID
     * @param id the id
     */
    public void setId(long id) {
        this.id = id;
    }

    /**
     * The instant (in GMT) of the event
     * @return the instant of the event
     */
    public Instant getEventDate() {
        return eventInstant;
    }

    /**
     * Set the instant of the Event
     * @param eventInstant the instant to set
     */
    public void setEventDate(Instant eventInstant) {
        this.eventInstant = eventInstant;
    }

    /**
     * The max Force used for the event
     * @return the max force used
     */
    public int getMaxForce() {
        return maxForce;
    }

    /**
     * Set the max force used for the Event
     * @param maxForce the value of the max force
     */
    public void setMaxForce(int maxForce) {
        this.maxForce = maxForce;
    }
}

当我从DB读到我的POJO时,代码工作得很有魅力,如下所示:

public List<PlcEventBean> fetchData(int offset, int limit, DataFilter filter) {
    Instant fromInstant = filter.getFromInstant();
    Instant toInstant = filter.getToInstant();
    String id  = filter.getId();
    List<PlcEventBean> plcEventBeans = context.select()
        .from(PLC_DATA)
        .where(
            PLC_DATA.EVENT_INSTANT.greaterThan(fromInstant)
                                    .and(PLC_DATA.EVENT_INSTANT.lessThan(toInstant))
                                    .and(PLC_DATA.ID.like("%" + id + "%"))
            )
            .offset(offset)
            .limit(limit)
            .fetchInto(PlcEventBean.class);
    logger.info("Fetched {} with offset: {} limit: {} with fromDateTime {}, toDateTime {}, textSearch {}"
        ,plcEventBeans.size()
        ,offset
        ,limit
        ,fromInstant
        ,toInstant
        ,id
    );
    return plcEventBeans;
}

但当我尝试在数据库中写入一些数据时,我在尝试生成新记录时遇到了一个异常:

public void generateRandomValues() {
    int nEvents = 40000;
    Random r = new Random(0);
    List<PlcEventBean> plcEvents = new ArrayList<>();

    for (long i = 0; i < nEvents; i++) {
        PlcEventBean eventBean = new PlcEventBean();
        eventBean.setId(i);
        eventBean.setEventDate(Instant.now().plus(i, ChronoUnit.MINUTES));
        eventBean.setMaxForce(Math.abs(r.nextInt()));
        plcEvents.add(eventBean);
    }
    PlcDataRecord plcDataRecord = context.newRecord(PLC_DATA, plcEvents);
    context.executeInsert(plcDataRecord);
}
org.jooq.exception.DataTypeException: Cannot convert from it.fox.plcwebgui.plc.PlcEventBean@2a389173 (class it.fox.plcwebgui.plc.PlcEventBean) to class java.time.LocalDateTime
    at org.jooq.tools.Convert$ConvertAll.fail(Convert.java:1200)
    at org.jooq.tools.Convert$ConvertAll.from(Convert.java:1089)
    at org.jooq.tools.Convert.convert0(Convert.java:324)
    at org.jooq.tools.Convert.convert(Convert.java:316)
    at org.jooq.tools.Convert.convert(Convert.java:387)
    at org.jooq.impl.DefaultDataType.convert(DefaultDataType.java:827)
    at org.jooq.impl.ConvertedDataType.convert(ConvertedDataType.java:114)
    at org.jooq.impl.Tools.setValue(Tools.java:2823)
    at org.jooq.impl.DefaultRecordUnmapper$IterableUnmapper.unmap(DefaultRecordUnmapper.java:189)
    at org.jooq.impl.DefaultRecordUnmapper.unmap(DefaultRecordUnmapper.java:102)
    at org.jooq.impl.AbstractRecord.from0(AbstractRecord.java:837)
    at org.jooq.impl.AbstractRecord.from(AbstractRecord.java:867)
    at org.jooq.impl.DefaultDSLContext$6.operate(DefaultDSLContext.java:4019)
    at org.jooq.impl.RecordDelegate.operate(RecordDelegate.java:130)
    at org.jooq.impl.DefaultDSLContext.newRecord(DefaultDSLContext.java:4015)
    at it.fox.plcwebgui.plc.PlcEventServiceDatabaseImp.generateRandomValues(PlcEventServiceDatabaseImp.java:120)
    at it.fox.plcwebgui.utils.db.PlcEventServiceDatabaseImpTest.generateRandomValuesTest01(PlcEventServiceDatabaseImpTest.java:128)

据我在文档中了解,转换器应该双向工作。我错过了什么?

当做

斯特凡诺

共有1个答案

龙俊英
2023-03-14

错误在于:

PlcDataRecord plcDataRecord = context.newRecord(PLC_DATA, plcEvents);

您想要将POJO列表转换为单个记录,这没有意义。将该逻辑转移到循环中,取而代之的是:

List<PlcDataRecord> records = new ArrayList<>();

for (long i = 0; i < nEvents; i++) {
    PlcEventBean eventBean = new PlcEventBean();
    eventBean.setId(i);
    eventBean.setEventDate(Instant.now().plus(i, ChronoUnit.MINUTES));
    eventBean.setMaxForce(Math.abs(r.nextInt()));
    records.add(context.newRecord(PLC_DATA, eventBean));
}

context.batchInsert(records);

只需将类型重写为SQLDataType。即时而不是滚动您自己的转换器:

forcedType {
    name = 'INSTANT'
    includeTypes = 'TIMESTAMP.*'
}
 类似资料:
  • 在我的Oracle数据库中,我有存储为VARCHAR的数量值。从数据库中检索记录时,我希望将它们映射到一个POJO,其中金额值表示为double。不幸的是,我不能使用强制类型,因为在数据库中,所有内容都存储为VARCHAR,并且没有模式将列标识为包含金额值的列。 我正在查看jOOQ转换器,这似乎是我想要的。因此,我为此创建了一个jOOQ转换器: 然而,每当我想使用将数据库记录映射到我的POJO时,

  • f)现在我必须将CSV的内容存储到数据库中,所以我使用了jdbc-output-adapter 我尝试了不同的选项来获取bean值,但都不起作用。如何从包含POJO列表的有效负载中获取jdbc-output-adapter中的bean值

  • 问题内容: 我正在将Jersey用于REST WS,并且得到的响应为JSON。 我想将此响应转换为POJO。怎么做 ? 问题答案: 要在Java和JSON之间进行转换,有很多可供选择的API 。 您可以“手动”遍历JSON组件并提取值以填充Java对象,或者可以使用JSON到Java的绑定API来解决许多低级映射问题。

  • 问题内容: 这似乎有点不正常,但我在寻找一个有效的方式来变换/映射成。 我将模型的一些信息存储在json文件中,并且我必须支持模型的几个版本。 我要做的是将json文件加载到JsonNode的内存中,应用一些版本控制策略以使其与我的Model的最新版本匹配。 除非有更快的方法,否则我可能最终将手动将其应用于模型 问题答案: 在Jackson 2.4中,可以进行如下转换: 杰克逊在哪儿? 在旧版的J

  • 问题内容: 我一直在研究Jackson,但似乎我必须将Map转换为JSON,然后将所得的JSON转换为POJO。 有没有一种方法可以将Map直接转换为POJO? 问题答案: 好吧,您也可以使用Jackson来实现。(由于您正在考虑使用杰克逊,因此似乎更舒适)。 使用的方法: 无需转换为JSON字符串或其他内容;直接转换的速度要快得多。

  • 我试着把POJO转换成protobuf。这和我想做的是一样的。(https://github.com/BAData/protobuf-converter,将协议缓冲区转换为POJO) 但是,它不支持protobuf中的映射类型。所以当我试图转换protobuf的地图时 有什么简单的方法做这项工作吗?