繁体   English   中英

JOOQ 映射问题(DataTypeException)

[英]JOOQ problem with mapping (DataTypeException)

将记录映射到实体时出现此异常:

org.jooq.exception.DataTypeException: No Converter found for types java.util.UUID and java.util.List
at org.jooq.impl.Tools.converterOrFail(Tools.java:1208) ~[jooq-3.15.0.jar:na]
at org.jooq.impl.Tools.converterOrFail(Tools.java:1217) ~[jooq-3.15.0.jar:na]
at org.jooq.impl.AbstractRecord.get(AbstractRecord.java:351) ~[jooq-3.15.0.jar:na]
at org.jooq.impl.DefaultRecordMapper$ImmutablePOJOMapper.set(DefaultRecordMapper.java:1146) ~[jooq-3.15.0.jar:na]
at org.jooq.impl.DefaultRecordMapper$ImmutablePOJOMapper.mapNonnested(DefaultRecordMapper.java:1137) ~[jooq-3.15.0.jar:na]
at org.jooq.impl.DefaultRecordMapper$ImmutablePOJOMapper.map(DefaultRecordMapper.java:1124) ~[jooq-3.15.0.jar:na]
at org.jooq.impl.DefaultRecordMapper.map(DefaultRecordMapper.java:610) ~[jooq-3.15.0.jar:na]
at org.jooq.impl.DelayedRecordMapper.map(DelayedRecordMapper.java:69) ~[jooq-3.15.0.jar:na]
at org.jooq.RecordMapper.apply(RecordMapper.java:80) ~[jooq-3.15.0.jar:na]
at org.jooq.RecordMapper.apply(RecordMapper.java:65) ~[jooq-3.15.0.jar:na]
at java.base/java.util.stream.Collectors.lambda$mapping$13(Collectors.java:469) ~[na:na]
at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) ~[na:na]
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na]
at org.jooq.impl.AbstractCursor.collect(AbstractCursor.java:78) ~[jooq-3.15.0.jar:na]
at org.jooq.impl.ResultQueryTrait.collect(ResultQueryTrait.java:358) ~[jooq-3.15.0.jar:na]
at org.jooq.impl.ResultQueryTrait.fetchInto(ResultQueryTrait.java:1423) ~[jooq-3.15.0.jar:na]
at com.example.jooqsample.posts.JOOQPostRepository.getAll(JOOQPostRepository.java:45) ~[classes/:na]
at com.example.jooqsample.posts.PostFacade.getAllPosts(PostFacade.java:34) ~[classes/:na]
at com.example.jooqsample.posts.rest.PostController.getAllPosts(PostController.java:27) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.23.jar:5.3.23]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:670) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.23.jar:5.3.23]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:779) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

实体:

@AllArgsConstructor(access = AccessLevel.PACKAGE)
@Getter
@ToString
@EqualsAndHashCode(of = "id")
class Post {

    private UUID id;

    private String content;

    private Instant createdAt;

    private List<Comment> comments;

PostDTO toDTO() {
    return PostDTO
            .builder()
            .id(this.id)
            .content(this.content)
            .comments(this.comments.stream().map(Comment::toDTO).toList())
            .build();
    }
 }

@AllArgsConstructor(access = AccessLevel.PACKAGE)
@Getter
@ToString
@EqualsAndHashCode(of = "id")
class Comment {
    private UUID id;

    private String content;

    private Instant createdAt;

    UUID postId;

CommentDTO toDTO() {
    return new CommentDTO(this.id, this.content);
  }
}

方法:

public List<Post> getAll() {
    return dslContext
            .select()
            .from(POSTS)
            .leftJoin(COMMENTS)
            .onKey()
            .fetchInto(Post.class);
}
  • JOOQ版本:3.15
  • Spring 引导版本:2.7.5
  • Java 版本:17

为什么你的方法不起作用

您正在从POSTSCOMMENTS之间的一对多关系创建一个平面结果集,然后,您期望 jOOQ 的DefaultRecordMapper (通过fetchInto(Class)方法)再次自动为您删除重复的那些平面结果. 但这不是 jOOQ 中的工作方式。 虽然知道查询中POSTSCOMMENTS之间的关系,但平面 jOOQ Result却不知道。 没有明显的方法可以自动删除重复数据。 想象一下,您在Post中有多个嵌套的 collections ,那将如何工作?

使用MULTISET嵌套collections

嵌套 collections 的最 jOOQ 和 SQL 惯用方式是使用MULTISET以及ad-hoc 转换器,例如:

List<Post> result =
dslContext
    .select(
        POSTS.ID,
        POSTS.CONTENT,
        POSTS.CREATED_AT,
        multiset(
            select(COMMENTS.ID, COMMENTS.CONTENT, COMMENTS.CREATED_AT)
            .from(COMMENTS)
            .where(COMMENTS.POST_ID.eq(POSTS.ID))
        ).convertFrom(r -> r.map(Records.mapping(Comment::new))))
    .from(POSTS)
    .fetch(Records.mapping(Post::new));

@Lukas埃德尔

我已经使用 multisetAgg 编写了这个方法。 它工作正常,但我不确定它应该是这样的:

  List<Post> getAllPost() {
    List<Post> result =
            dslContext
                    .select(
                            POSTS.ID,
                            POSTS.CONTENT,
                            POSTS.CREATED_AT,
                            multisetAgg(
                                    COMMENTS.ID, COMMENTS.CONTENT, COMMENTS.CREATED_AT, COMMENTS.POST_ID

                            ).as("comments").convertFrom(r -> r.into(Comment.class))
                    )
                    .from(POSTS)
                    .leftJoin(COMMENTS).on(COMMENTS.POST_ID.eq(POSTS.ID))
                    .groupBy(POSTS.ID)
                    .fetchInto(Post.class);
    return result;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM