Hibernate Mapping Issue: Unable to Map DTO Using TypedQuery

95 Views Asked by At

I'm facing a problem while trying to map a DTO using TypedQuery. Despite trying several approaches, the mapping doesn't seem to work as expected. I have ensured that the parameters are correctly set, and the relationship with the child table is appropriately defined.

I need assistance in identifying the mistakes in my code. Please review the following changes and point out any issues that might be causing the problem.

My Service class:

public OrganizationDetailDTO getOrganizationDetailForAgent(Long anOrganizationId) throws ApplicationException, AccessDeniedException {
        // Create DTO and necessary objects
        OrganizationDetailDTO organizationDTO;
        try {
            // Log request information
            LOGGER.info("#2 Get OrganizationByIdWithParent request received in Organization Service with OrganizationId: " + anOrganizationId);

            organizationDTO = this.findOrganizationDetailDTO(OrganizationDetailDTO.class, anOrganizationId);
            // Retrieve organization by ID

            // Check if organization exists
            if (organizationDTO == null) {
                LOGGER.info("No Organization Found Against Id " + anOrganizationId);
                throw new Exception("No Organization Found Against Id");
            }
}



public <T> T findOrganizationDetailDTO(Class<T> organizationDetailDTOClass, Long id) {
        String queryString = "SELECT NEW com.alsharqi.org.organization.OrganizationDetailDTO(o.id, o.squad, o.squadId, o.creditHoldOverride, o.creditLimit, o.creditTermName, " +
                "o.creditTerm, o.vatRegNumber, o.isActive, o.accountManagerUUID, o.accountManagerName, o.logisticManagerUUID, o.logisticManagerName, o.escalationManagerUUID, " +
                "o.escalationManagerName,o.portalAccess,o.systemActive,o.parent.id) FROM Organization o WHERE o.id = :id";
        TypedQuery<T> query = entityManager.createQuery(queryString, organizationDetailDTOClass);
        query.setParameter("id", id);

        try {
            return query.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

OrganizationDTO class:

@Setter
@Getter
@NoArgsConstructor
public class OrganizationDetailDTO {
    @Column(name = "organization_id")
    private Long id;

    private String squad;
    private String squadId;

    private String creditHoldOverride;
    private Double creditLimit;
    private String creditTermName;
    private Double creditTerm;
    private String vatRegNumber;
    private boolean isActive;

    private Long accountManagerUUID;
    private String accountManagerName;
    private Long logisticManagerUUID;
    private String logisticManagerName;
    private Long escalationManagerUUID;
    private String escalationManagerName;
    private boolean portalAccess;
    private int  systemActive;
    private Long parent;
    public OrganizationDetailDTO(Long id, String squad, String squadId, String creditHoldOverride, Double creditLimit, String creditTermName, Double creditTerm,
                                 String vatRegNumber, boolean isActive, Long accountManagerUUID, String accountManagerName, Long logisticManagerUUID,
                                 String logisticManagerName, Long escalationManagerUUID, String escalationManagerName,boolean portalAccess,Integer  systemActive,Long parent) {
        this.id = id;
        this.squad = squad;
        this.squadId = squadId;
        this.creditHoldOverride = creditHoldOverride;
        this.creditLimit = creditLimit;
        this.creditTermName = creditTermName;
        this.creditTerm = creditTerm;
        this.vatRegNumber = vatRegNumber;
        this.isActive = isActive;
        this.accountManagerUUID = accountManagerUUID;
        this.accountManagerName = accountManagerName;
        this.logisticManagerUUID = logisticManagerUUID;
        this.logisticManagerName = logisticManagerName;
        this.escalationManagerUUID = escalationManagerUUID;
        this.escalationManagerName = escalationManagerName;
        this.portalAccess=portalAccess;
        this.systemActive=systemActive;
        this.parent=parent;

    }



    private ContactDTO adminInfo = new ContactDTO();

}

Entity Class: enter image description here

Tried all possible solutions but still facing this issue:

com.hp.org.util.ApplicationException: org.hibernate.QueryException: could not instantiate class [com.hp.org.organization.OrganizationDetailDTO] from tuple
at com.hp.org.api.OrganizationService.getOrganizationDetailForAgent(OrganizationService.java:3347) ~[main/:?]
at com.hp.org.api.OrganizationService$$FastClassBySpringCGLIB$$59b45cac.invoke(<generated>) ~[main/:?]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.13.RELEASE.jar:5.0.13.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.0.13.RELEASE.jar:5.0.13.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.13.RELEASE.jar:5.0.13.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.0.13.RELEASE.jar:5.0.13.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.13.RELEASE.jar:5.0.13.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.13.RELEASE.jar:5.0.13.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.13.RELEASE.jar:5.0.13.RELEASE]
at com.hp.org.api.OrganizationService$$EnhancerBySpringCGLIB$$c94a2754.getOrganizationDetailForAgent(<generated>) ~[main/:?]
2

There are 2 best solutions below

0
On BEST ANSWER

I see no error in your code or configurations. Have you verified your data for null values? Try checking your record if it contains null values for the below mentioned keys. If it does, I will suggest that you use Non-Primitive data types in your DTO. Since you've used primitive data types and they don't accept null values.

    private Boolean portalAccess;
    private Integer  systemActive;
    private Integer  isActive;

Use Boolean instead of boolean and Integer instead of int. Hopefully this should resolve your issue.

3
On

I tried to replicate your issue but my project executed successfully. I believe there are some errors in your configurations, you can compare them with my example and check if something is wrong in your project.

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.3'
    id 'io.spring.dependency-management' version '1.1.3'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation  'org.projectlombok:lombok:1.18.28'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok:1.18.20'
}

tasks.named('test') {
    useJUnitPlatform()
}

ContactDTO

package com.example.typeddemo;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
public class ContactDTO {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "id", nullable = false)
    private Long id;

}

Organization

package com.example.typeddemo;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Entity
@Getter
@Setter
@ToString
public class Organization {

    @Getter
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "id", nullable = false)
    private Long id;
    private String squad;
    private String squadId;
    private String creditHoldOverride;
    private Double creditLimit;
    private String creditTermName;
    private Double creditTerm;
    private String vatRegNumber;
    private boolean isActive;
    private Long accountManagerUUID;
    private String accountManagerName;
    private Long logisticManagerUUID;
    private String logisticManagerName;
    private Long escalationManagerUUID;
    private String escalationManagerName;
    private boolean portalAccess;
    private int systemActive;
    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Organization parent;

}

OrganizationDetailDTO

package com.example.typeddemo;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Transient;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Setter
@Getter
@Entity
@ToString
public class OrganizationDetailDTO {
    @Column(name = "organization_id")
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    private String squad;
    private String squadId;
    private String creditHoldOverride;
    private Double creditLimit;
    private String creditTermName;
    private Double creditTerm;
    private String vatRegNumber;
    private boolean isActive;
    private Long accountManagerUUID;
    private String accountManagerName;
    private Long logisticManagerUUID;
    private String logisticManagerName;
    private Long escalationManagerUUID;
    private String escalationManagerName;
    private boolean portalAccess;
    private int  systemActive;
    private Long parent;

    public OrganizationDetailDTO() {

    }
    public OrganizationDetailDTO(Long id, String squad, String squadId, String creditHoldOverride, Double creditLimit, String creditTermName, Double creditTerm,
            String vatRegNumber, boolean isActive, Long accountManagerUUID, String accountManagerName, Long logisticManagerUUID,
            String logisticManagerName, Long escalationManagerUUID, String escalationManagerName,boolean portalAccess,Integer  systemActive,Long parent) {
        this.id = id;
        this.squad = squad;
        this.squadId = squadId;
        this.creditHoldOverride = creditHoldOverride;
        this.creditLimit = creditLimit;
        this.creditTermName = creditTermName;
        this.creditTerm = creditTerm;
        this.vatRegNumber = vatRegNumber;
        this.isActive = isActive;
        this.accountManagerUUID = accountManagerUUID;
        this.accountManagerName = accountManagerName;
        this.logisticManagerUUID = logisticManagerUUID;
        this.logisticManagerName = logisticManagerName;
        this.escalationManagerUUID = escalationManagerUUID;
        this.escalationManagerName = escalationManagerName;
        this.portalAccess=portalAccess;
        this.systemActive=systemActive;
        this.parent=parent;

    }

    @OneToOne
    @JoinColumn(name = "admin_info_id")
    @Transient
    private ContactDTO adminInfo = new ContactDTO();

}

OrganizationService

package com.example.typeddemo;

import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.TypedQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrganizationService {

    Logger LOGGER = LoggerFactory.getLogger(OrganizationService.class);

    @Autowired
    EntityManager entityManager;

    public OrganizationDetailDTO getOrganizationDetailForAgent(Long anOrganizationId)
            throws Exception {
        // Create DTO and necessary objects
        OrganizationDetailDTO organizationDTO;
        // Log request information
        LOGGER.info("#2 Get OrganizationByIdWithParent request received in Organization Service with OrganizationId: "
                + anOrganizationId);

        organizationDTO = this.findOrganizationDetailDTO(OrganizationDetailDTO.class, anOrganizationId);
        // Retrieve organization by ID

        // Check if organization exists
        if (organizationDTO == null) {
            LOGGER.info("No Organization Found Against Id " + anOrganizationId);
            throw new Exception("No Organization Found Against Id");
        }

        return organizationDTO;
    }

    public <T> T findOrganizationDetailDTO(Class<T> organizationDetailDTOClass, Long id) {
        String queryString =
                "SELECT NEW com.example.typeddemo.OrganizationDetailDTO(o.id, o.squad, o.squadId, o.creditHoldOverride, o.creditLimit, o.creditTermName, "
                        +
                        "o.creditTerm, o.vatRegNumber, o.isActive, o.accountManagerUUID, o.accountManagerName, o.logisticManagerUUID, o.logisticManagerName, o.escalationManagerUUID, "
                        +
                        "o.escalationManagerName,o.portalAccess,o.systemActive,o.parent.id) FROM Organization o WHERE o.id = :id";
        TypedQuery<T> query = entityManager.createQuery(queryString, organizationDetailDTOClass);
        query.setParameter("id", id);

        try {
            return query.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }
}

RepositoryOrganization

package com.example.typeddemo;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface RepositoryOrganization extends JpaRepository<Organization, Long> {

}

RepositoryOrgDetail

package com.example.typeddemo;

import org.springframework.data.jpa.repository.JpaRepository;

@org.springframework.stereotype.Repository
public interface RepositoryOrgDetail extends JpaRepository<OrganizationDetailDTO, Long> {

}

TypedDemoApplication

package com.example.typeddemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TypedDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(TypedDemoApplication.class, args);
    }

}

TypedDemoApplicationTests

package com.example.typeddemo;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class TypedDemoApplicationTests {

    @Autowired
    OrganizationService organizationService;
    @Autowired
    RepositoryOrgDetail repositoryOrgDetail;
    @Autowired
    RepositoryOrganization repositoryOrganization;

    @Test
    void contextLoads() throws Exception {

        Organization parent = new Organization();
        repositoryOrganization.saveAndFlush(parent);
        OrganizationDetailDTO organisation = new OrganizationDetailDTO(parent.getId(),
                "squad",
                "sq1",
                "credit",
                Double.valueOf(20),
                "term",
                Double.valueOf(10),
                "vat",
                false,
                10L,
                "account",
                10L,
                "log",
                10L,
                "esc",
                false,
                10,
                parent.getId());
        repositoryOrgDetail.saveAndFlush(organisation);

        OrganizationDetailDTO organizationDetailForAgent = organizationService.getOrganizationDetailForAgent(parent.getId());
        Assertions.assertNotNull(organizationDetailForAgent);
    }

}

I hope this will help. Good luck!