在java.sql.Timestamp和java.time.Instant之间转换时遇到问题,使用JOOQ



使用JOOQ转换器在java.sql.Timestamp和java.time.Instant之间转换时遇到问题。

这是我正在使用的代码的简化版本。

public class User {
private static final Converter<Timestamp, Instant> MY_CONVERTER= Converter.of(
Timestamp.class,
Instant.class,
t -> t == null ? null : t.toInstant(),
i -> i == null ? null : Timestamp.from(i)
)
public static Table<?> table = DSL.table("user");
public static Field<String> name = DSL.field(DSL.name(table.getName(), "name"), String.class);
public static Field<Instant> name = DSL.field(DSL.name(table.getCreated(), "created"), SQLDataType.TIMESTAMP.asConvertedDataType(Converter.of(MY_CONVERTER)));    
}
private class UserDto {
private String name;
private Instant created;
// getters, setters, etc.
}
public class UserWriter {
// constructor with injected DefaultDSLContext etc..
public void create(UserDto user) {
dslContext.insertInto(User.table, User.firstName, User.lastName)
.values(user.getName(), user.getCreated())
.execute();
}
}
public class UserReader {
// constructor with injected DefaultDSLContext etc..
public Result<Record> getAll() {
return dslContext.select().from(User.table).fetch();
}
}
public class UserService {
// constructor with injected UserReader etc..
public Collection<UserDto> getAll() {
return userReader
.getAll()
.stream()
.map(Users::from)
.collect(Collectors.toList());
}
}
public class Users {
public static UserDto from(Record record) {
UserDto user = new UserDto();
user.setName(record.get(User.name));
user.setCreated(record.get(User.created);
return user;
}
}

当我创建一个新的用户时,转换器被调用,插入工作正常。但是,当我选择Users时,转换器不会被调用,Users::from方法中的record.get(User.created)调用会返回一个时间戳(因此会失败,因为UserDto.setCreated需要一个Instant(。

有什么想法吗?

谢谢!

为什么没有应用转换器

从你表达问题的方式来看(你没有发布你尝试过的SELECT语句(,我假设你没有明确地传递所有的列表达式。但是,jOOQ如何能够找出表中有哪些列呢?您在some类中声明了some列表达式,但该类没有遵循jOOQ已知的任何结构。让jOOQ获取所有已知列的唯一方法是使用代码生成使它们为jOOQ所知(见下文(。

当然,您可以让User扩展内部org.jooq.impl.TableImpl类,并使用内部API来注册Field值。但是,如果您可以生成这些代码,为什么要手动执行呢?

代码生成

我将重复我上一个问题的要点,即:请使用代码生成器。我现在已经写了一整篇关于你为什么要这么做的文章。一旦jOOQ通过代码生成了解了您的所有元数据,您就可以自动选择所有列,如下所示:

UserRecord user = ctx
.selectFrom(USER)
.where(USER.ID.eq(...))
.fetchOne();

不仅如此,您还可以使用<forcedType>将数据类型配置为INSTANT,因此您不必每次都担心数据类型转换。

我再怎么强调也不为过,而且我经常感到惊讶的是,有多少项目试图在没有代码生成的情况下使用jOOQ,这消除了jOOQ的很多功能。使用代码生成的主要原因是,如果您的模式是动态的,但由于您有User类,它显然不是动态的。

最新更新