【问题标题】:How to map results of a Hibernate Query to a DTO object?如何将休眠查询的结果映射到 DTO 对象?
【发布时间】:2020-12-08 21:32:23
【问题描述】:

我的Java 项目中有以下 3 个Hibernate 实体:

公司状态

@Entity(name = "company_status")
@Table(name = "company_status")
public class CompanyStatus implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @JsonProperty
    @Column(name = "company_status_id")
    private Integer companyStatusId;

    @JsonProperty
    @Column(name = "company_status_label")
    private String companyStatusLabel;

}

员工状态

@Entity(name = "employee_status")
@Table(name = "employee_status")
public class EmployeeStatus implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonProperty
    @Column(name = "employee_status_id")
    private Integer employeeStatusId;

    @JsonProperty
    @Column(name = "employee_status_name")
    private String employeeStatusName;

    // many other fields
}

CompanyStatusEmployeeStatus(链接两个实体的实体 - 一对一关系)

@Entity(name = "company_status_employee_status")
@Table(name = "company_status_employee_status")
public class CompanyStatusEmployeeStatus implements Serializable {

    // int(20)
    @Id
    @JsonProperty
    @Column(name = "company_status_id")
    private Integer companyStatusId;

    // int(20)
    @JsonProperty
    @Column(name = "employee_status_id")
    private Integer employeeStatusId;
}

我只想将 JSON 响应中的必要字段返回到前端,因此我创建了一个较小的 CompanyStatusDTO 对象,该对象还嵌套了一个 EmployeeStatusDTO 列表

CompanyStatusDTO

public class CompanyStatusDTO {

    @JsonProperty
    private Integer companyStatusId;

    @JsonProperty
    private String companyStatusLabel;

    @JsonProperty
    private List <EmployeeStatusDTO> employeeStatusDTOs;

}

EmployeeStatusDTO

public class EmployeeStatusDTO {

    @JsonProperty
    private Integer employeeStatusId;

    @JsonProperty
    private String employeeStatusName;

}

但是,我对使用 Hibernate 比较陌生 - 有没有一种方法可以创建一个查询,将结果直接从我的 MySQL DB 映射到我的 CompanyStatusDTOobject?

如果是这样,我该怎么做?

【问题讨论】:

    标签: java mysql json hibernate dto


    【解决方案1】:

    您可以使用 NativeQuery 将查询结果直接映射到您想要的 DTO(数据类型必须匹配)

    String q = "select ... from table"; // your sql query
    Query query = getEntityManager().createNativeQuery(q, "EmployeeStatusDTO");
    EmployeeStatusDTO data = (EmployeeStatusDTO) query.getSingleResult();
    return data;
    

    【讨论】:

    • 好的,我可以使用连接查询吗?我不确定,因为最近才开始基本休眠
    • 是的,支持连接,您还可以参数化您的查询并添加 where 子句。对于员工列表,请使用 query.getResultList() 而不是 query.getSingleResult()
    • 您可以将代码分为两部分:1) 获取公司状态,运行一个查询并部分填充 CompanyStatusDTO 2) 获取公司 ID 加入查询的 List 并填充您的employeeStatusDTO公司状态DTO
    【解决方案2】:

    这是Blaze-Persistence Entity Views 的完美用例。

    我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

    如果您稍微调整CompanyStatusCompanyStatusEmployeeStatus 实体并添加以下内容:

    public class CompanyStatus implements Serializable {
      //...
      @OneToMany(mappedBy = "companyStatus")
      private Set<CompanyStatusEmployeeStatus> employeeStatuses;
    }
    
    public class CompanyStatusEmployeeStatus implements Serializable {
        //...
        @JsonProperty
        @ManyToOne(fetch = LAZY)
        @JoinColumn(name = "company_status_id", insertable = false, updatable = false)
        private CompanyStatus companyStatus;
    
        @JsonProperty
        @ManyToOne(fetch = LAZY)
        @JoinColumn(name = "employee_status_id", insertable = false, updatable = false)
        private EmployeeStatus employeeStatus;
    }
    

    您的模型可能如下所示:

    @EntityView(CompanyStatus.class)
    public interface CompanyStatusDTO {
        @IdMapping
        Integer getCompanyStatusId();
        String getCompanyStatusLabel();
        @Mapping("employeeStatuses.employeeStatus")
        List<EmployeeStatusDTO> getEmployeeStatusDTOs();
    }
    @EntityView(EmployeeStatus.class)
    public interface EmployeeStatusDTO {
        @IdMapping
        Integer getEmployeeStatusId();
        String getEmployeeStatusName();
    }
    

    查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

    CompanyStatusDTO c = entityViewManager.find(entityManager, CompanyStatusDTO.class, id);

    Spring Data 集成让您可以像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

    【讨论】:

      【解决方案3】:

      你可以试试这个:

      public class Dao{
      
          private SessionFactory sessionFactory;
          
          public Dao(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
          }
      
          public <T> T save(final T o){
            return (T) sessionFactory.getCurrentSession().save(o);
          }
      
      
          public void delete(final Object object){
            sessionFactory.getCurrentSession().delete(object);
          }
      
          public <T> T get(final Class<T> type, final Long id){
            return (T) sessionFactory.getCurrentSession().get(type, id);
          }
      
          public <T> List<T> getAll(final Class<T> type) {
            final Session session = sessionFactory.getCurrentSession();
            final Criteria crit = session.createCriteria(type);
        return crit.list();
          }
      // and so on, you should get the idea
      

      然后你就可以在服务层这样访问了:

          private Dao dao;
         
          @Transactional(readOnly = true)
          public List<MyEntity> getAll() {
            return dao.getAll(MyEntity.class);
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-05
        • 2021-08-13
        • 2011-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-11
        • 1970-01-01
        相关资源
        最近更新 更多