4

Is it possible to use JpaRepository without entity? In this case, replacing it with a DTO.

as follows the example

 @Repository
public interface BffRepository extends JpaRepository<BffDTO, String> {

@Query(nativeQuery = true, value = "select\n"
        + "ent.name as enterprise_name, dep.name as department_name,\n"
        + "sq.name as squad_name, acc.firstname as job_owner_name,\n"
        + "tpt.name as test_template_name, job.name, job.job_blocked, job.job_removed,\n"
        + "job.bot_scm_branch, job.bot_scm_url, job.schedule_startdate,\n"
        + "job.expiration_date, job.timestamp,job.uuid,job.schedule_starttime,\n"
        + "tpt.job_execution_timeout\n"
        + "from portal.jobs job\n"
        + "left join portal.enterprises ent on (ent.uuid = job.enterprise_id)\n"
        + "left join portal.departments dep on (dep.uuid = job.department_id)\n"
        + "left join portal.squads sq on (sq.uuid = job.squad_id)\n"
        + "left join portal.accounts acc on (acc.uuid = job.job_owner)\n"
        + "left join portal.test_plan_templates tpt on (tpt.uuid = job.template_id) where\n"
        + "job.job_owner = ?1 and job.job_removed = false order by timestamp desc;")
List<BffDTO>buscarPorJobOwner(String jobOwner);

Are there alternatives for this case?

NOTE: the DTO is already mapped, but I would not like to create a view to transform this DTO into an Entity.

I already validated this topic, but without major advances Use JpaRepository interaction style without entity

i'm trying this

Interface -

public interface BffDTOInterface2 {

String uuid();

String enterprise_name();

String department_name();

String squad_name();

String job_owner_name();

String test_template_name();

String name();

Boolean job_blocked();

Boolean job_removed();

String bot_scm_branch();

String bot_scm_url();

String schedule_startdate();

String expiration_date();

String timestamp();

String schedule_starttime();

Integer job_execution_timeout();

@Transient
String status();

}

I'm having this error

Caused by: java.lang.IllegalArgumentException: Not a managed type: interface br.com.cloud.api.domain.dto.BffDTOInterface2
Giorgi Tsiklauri
  • 9,715
  • 8
  • 45
  • 66
Rodgans
  • 43
  • 1
  • 5

4 Answers4

3

You can use Projections based on interfaces.

e.g

  1. Create your native-query givin it column a alias. select name as fullName, age as age from person.

  2. Create a Interface that represents your DTO with get-methods to every alias of your native query.

interface MyDTO {
   String getFullName();
   Integer getAge();
} 
  1. The return type of your query now can be this MyDTO
@Query(value = "select name as fullName, age as age from person", nativeQuery=true)
List<MyDTO> findMyDTO();
2

Is it possible to use JpaRepository without entity?

No, it is not, and it would completely defeat the purpose of JPA, by definition.

JPA is the persistence specification that enables ORM - Object Relational Mapping - that is, you map Java objects to database tables' entries/rows, and Java types to database tables, respectively.

DTO (Data Transfer Object) has nothing to do with ORM, and it serves different purpose (I recommend you to read this article for DTO vs. Entity matter) - transferring data through Java objects - and it usually serves the middle layer, for converting persistent objects(@Entitys) into objects to be used in the web layer (DTOs), and vice versa.

If you really want to avoid persistence layer models (@Entitys), you may go for JDBC abstractions (e.g. Spring Data JDBC), native queries, JPQL, HQL, or a bare JDBC API (which I wouldn't recommend).

Giorgi Tsiklauri
  • 9,715
  • 8
  • 45
  • 66
2

but you can try this.

What you can do is you can create your own custom repository class. First, you would have some service class that calls repository class. also notice that we have custom models for the result set of SQL queries.

@Service
public class CustomService {

    @Autowired
    private CustomRepository repository;

    public List<CustomResponse> getAllResult(String id) {

        List<Object[]> items = repository.getAllResult(id);
        List<CustomResponse> customResponseList = new ArrayList();
        for (Object[] item: items) {
            CustomResponse c = new CustomResponse();
            c.setTestValue1(String.valueOf(item[0]));
            c.setTestValue2(String.valueOf(item[1]));
            customResponseList.add(c);
        }

        return customResponseList;
    }

}

and your repository class will be look like this.

@Repository
public class CustomRepository {

    @Autowired
    private EntityManager entityManager;

    public List<Object[]> getAllResult(String id) {
        Query q = (Query) entityManager.createNativeQuery("SELECT\n" +
                "        users.user_id as user_id,\n" +
                "        users.email as user_email\n" +
                "        FROM Users\n" +
                "        WHERE users.parent_id = :parent_id;");
        q.setParameter("parent_id", id);
        List<Object[]> results = q.getResultList();
        return results;
    }

}

Also you might want to have your own model for that. (like entities)

public class CustomResponse {

    private String testValue1;
    private String testValue2;

    public String getTestValue1() {
        return testValue1;
    }

    public void setTestValue1(String testValue1) {
        this.testValue1 = testValue1;
    }

    public String getTestValue2() {
        return testValue2;
    }

    public void setTestValue2(String testValue2) {
        this.testValue2 = testValue2;
    }
}
Jin Lim
  • 1,759
  • 20
  • 24
0

This is possible. Define base entity and have one column. If you dont want this to exist in database, turn off ddl-auto in application.propeties.

spring.jpa.hibernate.ddl-auto=none

    @Entity
    @Data
    public class BaseEntity {
        @Id
        private Long id;
    }

and use any custom query with any other dao extending jpa repository with BaseEntity.

public interface EmployeeDao extends JpaRepository<BaseEntity, Long> {

    @Query(value = "select name from employee where employee_number = ?", nativeQuery = true)
    Optional<Employee> get(String employeeNumber);
}

public interface Employee{

    String getName();
   
}
Vivek Adhikari
  • 221
  • 2
  • 7