【问题标题】:Is it possible to use JpaRepository without entity?是否可以在没有实体的情况下使用 JpaRepository?
【发布时间】:2022-12-22 14:37:47
【问题描述】:

是否可以在没有实体的情况下使用JpaRepository?在这种情况下,将其替换为 DTO。

如下例

 @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);

这种情况有其他选择吗?

注意:DTO 已经映射,但我不想创建一个视图来将此 DTO 转换为实体。

我已经验证了这个主题,但没有重大进展 Use JpaRepository interaction style without entity

我正在尝试这个

界面 -

公共接口 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();

}

我有这个错误

Caused by: java.lang.IllegalArgumentException: Not a managed type: interface br.com.cloud.api.domain.dto.BffDTOInterface2

【问题讨论】:

    标签: java spring-boot jpa


    【解决方案1】:

    您可以使用基于接口的投影。

    例如

    1. 创建你的本机查询给它列一个别名。 select name as fullName, age as age from person。

    2. 创建一个代表您的 DTO 的接口,其中包含对本机查询的每个别名的获取方法。

      interface MyDTO {
         String getFullName();
         Integer getAge();
      } 
      
      1. 您查询的返回类型现在可以是这个 MyDTO
      @Query(value = "select name as fullName, age as age from person", nativeQuery=true)
      List<MyDTO> findMyDTO();
      

    【讨论】:

    • 在这种情况下,如果我必须使用实体,我会得到相同的回报注意:我会更新问题
    • 使用没有实体的 JpaRepository 根本行不通。
    • 你能告诉我你的存储库接口或类吗?
    【解决方案2】:

    是否可以在没有实体的情况下使用 JpaRepository?

    不,它不是,根据定义,它会完全破坏 JPA 的目的。

    JPA 是启用 ORM(对象关系映射)的持久性规范——即,您映射 Java对象到数据库表'条目/行, 和 Java 类型分别为数据库表。

    数据传输协议 (数据传输对象) 与 ORM 无关,它有不同的用途(我建议您阅读 this 文章了解 DTO 与实体问题) - 通过 Java 对象传输数据 - 它通常服务于中间层,用于转换持久对象( @Entitys) 转换为要在 Web 层 (DTO) 中使用的对象,反之亦然。

    如果你真的想避免持久层模型 (@Entitys),你可以选择 JDBC 抽象(例如 Spring Data JDBC)、本机查询、JPQL、HQL 或裸 JDBC API(我不推荐)。

    【讨论】:

    • 好答案。但是为什么还有很多其他 SO 答案说您可以将 @NamedNativeQuery 结果直接用于 DTO?
    【解决方案3】:

    但你可以试试这个。

    您可以做的是创建自己的自定义存储库类。首先,您将拥有一些调用存储库类的服务类。另请注意,我们为 SQL 查询的结果集提供了自定义模型。

    @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;
        }
    
    }
    

    您的存储库类将如下所示。

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

    此外,您可能希望拥有自己的模型。 (像实体)

    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;
        }
    }
    

    【讨论】:

      【解决方案4】:

      这个有可能。 定义基本实体并具有一列。如果您不想退出数据库,请在 application.propeties 中关闭 ddl-auto。

      spring.jpa.hibernate.ddl-auto=无

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

      并将任何自定义查询与任何其他扩展 jpa 存储库的 dao 一起使用。

      public interface EmployeeDao extends JpaRepository<BaseEntity, Long> {
      
          @Query(value = "select * from employee", nativeQuery = true)
          Optional<Employee> getRecentRequest(String employeeNumber);
      }
      
      public interface Employee{
      
          String getName();
         
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-16
        • 2020-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多