首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >尝试并未能在Spring中创建一个从3个表获取数据的DTO

尝试并未能在Spring中创建一个从3个表获取数据的DTO
EN

Stack Overflow用户
提问于 2020-12-22 15:16:18
回答 1查看 852关注 0票数 0

我正在编写一个API,该API将一个在线数据库连接到一个android应用程序,并一直被困在如何创建一个DTO的过程中,该DTO从相互连接的3个表中获取数据。

这是我正在编写的第一个API,我仍然在努力学习良好的实践,所以欢迎任何建议。

我已经到了一个地步,我真的不知道在哪里寻找答案,因为我找到的所有答案都是解释如何使用查询从单个表中获取数据(可能是使用错误的术语搜索,因为我不是英语母语)。

这些是我在API中创建的实体:

员工

代码语言:javascript
运行
复制
@Entity
@Table(name = "employees")
public class Employees {
    @Id
    @Column(name = "eid")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int eid;

    @Column(name = "first_name")
    private String first_name;

    @Column(name = "last_name")
    private String last_name;

    @Column(name = "birth_date")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
    private Date birth_date;

    @Column(name = "jid")
    private int jid;

//Getters setters constructors
}

工作

代码语言:javascript
运行
复制
@Entity
@Table(name = "jobs")
public class Jobs {
    @Id
    @Column(name = "jid")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int jid;

    @Column(name = "job_name")
    private String job_name;

//Getters setters constructors
}

凭据

代码语言:javascript
运行
复制
@Entity
@Table(name = "credentials")
@IdClass(CredentialsCID.class)
public class Credentials {
    @Id
    @Column(name = "username")
    private String username;

    @Id
    @Column(name = "is_admin")
    private byte is_admin;

    @Column(name = "password")
    private String password;

    @Column(name = "eid")
    private int eid;

//Getters setters constructors
}

这是dto类

EmployeesCustomDTO

代码语言:javascript
运行
复制
package com.example.accessingdatamysql.dto;

import com.example.accessingdatamysql.model.Contracts;
import com.example.accessingdatamysql.model.Credentials;
import com.example.accessingdatamysql.model.Employees;

public class EmployeesCustomDTO {
    private int eid;
    private String first_name;
    private String last_name;
    private String jid;
    private int hours;
    private String type;
    private byte is_admin;

    public EmployeesCustomDTO() {
    }

    public EmployeesCustomDTO(int eid, String first_name, String last_name, String jid, int hours, String type, byte is_admin) {
        this.eid = eid;
        this.first_name = first_name;
        this.last_name = last_name;
        this.jid = jid;
        this.hours = hours;
        this.type = type;
        this.is_admin = is_admin;
    }

    public int getEid() {
        return eid;
    }

    public void setEid(int eid) {
        this.eid = eid;
    }

    public String getFirst_name() {
        return first_name;
    }

    public void setFirst_name(String first_name) {
        this.first_name = first_name;
    }

    public String getLast_name() {
        return last_name;
    }

    public void setLast_name(String last_name) {
        this.last_name = last_name;
    }

    public String getJob_name() {
        return jid;
    }

    public void setJob_name(String job_name) {
        this.jid = job_name;
    }

    public int getHours() {
        return hours;
    }

    public void setHours(int hours) {
        this.hours = hours;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public byte getIs_admin() {
        return is_admin;
    }

    public void setIs_admin(byte is_admin) {
        this.is_admin = is_admin;
    }

    public EmployeesCustomDTO convertToDTO(Employees employees, Credentials credentials, Contracts contracts){
        EmployeesCustomDTO employeesCustomDTO = new EmployeesCustomDTO();
        employeesCustomDTO.setEid(employees.getEid());
        employeesCustomDTO.setFirst_name(employees.getFirst_name());
        employeesCustomDTO.setLast_name(employees.getLast_name());
        employeesCustomDTO.setJob_name(String.valueOf(employees.getJid())); // TODO: 19/12/2020 check if correct
        employeesCustomDTO.setType(contracts.getType());
        employeesCustomDTO.setHours(contracts.getHours());
        employeesCustomDTO.setIs_admin(credentials.getIs_admin());

        return employeesCustomDTO;
    }
}

然后,我向EmployeesRepo添加了以下查询(在MySQL工作台上试用它时,它的工作方式与我所希望的一样)

代码语言:javascript
运行
复制
@Repository
public interface EmployeesRepo extends JpaRepository<Employees, Integer> {
    @Query(value = "SELECT employees.eid,employees.first_name,employees.last_name,employees.jid,contracts.hours,contracts.type,credentials.is_admin " +
            "FROM employees,credentials,contracts " +
            "WHERE employees.eid = credentials.eid AND contracts.eid = employees.eid", nativeQuery = true)
    List<EmployeesCustomDTO> getCustomErgazomenoi();
}

及其服务中的下列方法

代码语言:javascript
运行
复制
@Override
    public List<EmployeesCustomDTO> getCustomErgazomenoi() {
        return employeesRepo.getCustomErgazomenoi();
    }

然后我调用控制器

代码语言:javascript
运行
复制
@GetMapping("/custom-employees")
    public List<EmployeesCustomDTO> getAllCustomEmployees(){return employeesService.getCustomErgazomenoi();}

当我将请求发送到端点时,我会得到以下错误:

邮递员:

代码语言:javascript
运行
复制
{
    "timestamp": "2020-12-22T16:40:28.542+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "message": "",
    "path": "/employees/custom-employees"
}

来自intellij的终端

代码语言:javascript
运行
复制
2020-12-22 18:40:28.527 ERROR 2948 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.core.co
nvert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.example.accessingdatamysql.dto.EmployeesCustomDTO]] with root cause

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.example.accessingdatamysql.dto.EmployeesCusto
mDTO]
        at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322) ~[spring-core-5.3.1.jar:5.3.1]
        at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195) ~[spring-core-5.3.1.jar:5.3.1]
        at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175) ~[spring-core-5.3.1.jar:5.3.1]
        at org.springframework.data.repository.query.ResultProcessor$ProjectingConverter.convert(ResultProcessor.java:309) ~[spring-data-commons-2.4.1.jar:2.4.1]
        at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.lambda$and$0(ResultProcessor.java:225) ~[spring-data-commons-2.4.1.jar:2.4.1]
        at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:236) ~[spring-data-commons-2.4.1.jar:2.4.1]
        at org.springframework.data.repository.query.ResultProcessor.processResult(ResultProcessor.java:156) ~[spring-data-commons-2.4.1.jar:2.4.1]
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:158) ~[spring-data-jpa-2.4.1.jar:2.4.1]
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:143) ~[spring-data-jpa-2.4.1.jar:2.4.1]
        at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) ~[spring-data-commons-2.4.1.jar:2.4.1]
        at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) ~[spring-data-commons-2.4.1.jar:2.4.1]
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152) ~[spring-data-commons-2.4.1.jar:2.4.1]
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:131) ~[spring-data-commons-2.4.1.jar:2.4.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.1.jar:5.3.1]
        at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.4.1.jar:2.4.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.1.jar:5.3.1]
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:371) ~[spring-tx-5.3.1.jar:5.3.1]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:134) ~[spring-tx-5.3.1.jar:5.3.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.1.jar:5.3.1]
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.1.jar:5.3.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.1.jar:5.3.1]
        at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:145) ~[spring-data-jpa-2.4.1.jar:2.4.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.1.jar:5.3.1]
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.1.jar:5.3.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.1.jar:5.3.1]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.1.jar:5.3.1]
        at com.sun.proxy.$Proxy120.getCustomErgazomenoi(Unknown Source) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[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:564) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.1.jar:5.3.1]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.1.jar:5.3.1]
        at com.sun.proxy.$Proxy77.getCustomErgazomenoi(Unknown Source) ~[na:na]
        at com.example.accessingdatamysql.services.impl.EmployeesServiceImpl.getCustomErgazomenoi(EmployeesServiceImpl.java:45) ~[classes/:na]
        at com.example.accessingdatamysql.controllers.EmployeesController.getAllCustomEmployees(EmployeesController.java:28) ~[classes/:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[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:564) ~[na:na]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.1.jar:5.3.1]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.1.jar:5.3.1]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.1.jar:5.3.1]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893) ~[spring-webmvc-5.3.1.jar:5.3.1]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:807) ~[spring-webmvc-5.3.1.jar:5.3.1]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.1.jar:5.3.1]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061) ~[spring-webmvc-5.3.1.jar:5.3.1]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.1.jar:5.3.1]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.1.jar:5.3.1]
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.1.jar:5.3.1]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.39.jar:4.0.FR]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.1.jar:5.3.1]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.39.jar:4.0.FR]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.1.jar:5.3.1]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.1.jar:5.3.1]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.1.jar:5.3.1]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
        at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]

虽然我找到了一些关于如何解决这个问题的答案,但我似乎无法让它在我的API上工作。有什么建议吗?

EN

回答 1

Stack Overflow用户

发布于 2020-12-22 15:41:11

您能提供EmployeesCustomDTO类的代码吗?看起来,您正在尝试执行DTO投影,这将要求您将SQL结果映射到DTO中的属性。

如果使用hibernate,可以在DTO和update查询上创建适当的构造函数以使用新的构造函数:

代码语言:javascript
运行
复制
@Query(value = "SELECT com.example.accessingdatamysql.dto.EmployeesCustomDTO(employees.eid,employees.first_name,employees.last_name,employees.jid,contracts.hours,contracts.type,credentials.is_admin) " +
               "FROM employees,credentials,contracts " +
               "WHERE employees.eid = credentials.eid AND contracts.eid = employees.eid")
List<EmployeesCustomDTO> getCustomErgazomenoi(); 

有关详细说明,请参见- https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/

无论哪种方式,您都必须提供从SQL结果集到DTO属性的映射。如果您遵循的是SQL和Java中的标准命名约定,则名称可能不相同--例如,您的查询引用是first_name,但我假设您的DTO将是firstName

看起来,如果使用本机查询:https://thorben-janssen.com/dto-projections/#DTO_projections_for_native_SQL_queries,也可以通过https://thorben-janssen.com/dto-projections/#DTO_projections_for_native_SQL_queries提供映射。

类似的堆栈溢出帖子:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65411193

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档