英文:
How to map results of a Hibernate Query to a DTO object?
问题
我在我的Java项目中有以下3个Hibernate实体:
CompanyStatus
@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;
}
Employee Status
@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相对较新 - 是否有一种方法可以创建一个查询,将结果直接映射到我的CompanyStatusDTO
对象中?
如果可以,我该如何实现这个需求呢?
英文:
I have the following 3 Hibernate
Entities within my Java
Project:
CompanyStatus
@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;
}
Employee Status
@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 linking the 2 entities- one to one relationship)
@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;
}
I only want to return the necessary fields in my JSON response to the front end , so In order to do so I have created a smaller CompanyStatusDTO
object that also has an EmployeeStatusDTO
list nested
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;
}
However, I am relatively new to using Hibernate - is there a way that I can create a query that will map results directly from my MySQL
DB to my CompanyStatusDTO
object?
If so, how can do I this?
答案1
得分: 1
你可以直接使用NativeQuery将查询结果映射到你想要的DTO中(数据类型必须匹配)
String q = "select ... from table"; // 你的SQL查询语句
Query query = getEntityManager().createNativeQuery(q, "EmployeeStatusDTO");
EmployeeStatusDTO data = (EmployeeStatusDTO) query.getSingleResult();
return data;
英文:
you can directly map query result to you desired DTO using NativeQuery (datatype must match)
String q = "select ... from table"; // your sql query
Query query = getEntityManager().createNativeQuery(q, "EmployeeStatusDTO");
EmployeeStatusDTO data = (EmployeeStatusDTO) query.getSingleResult();
return data;
答案2
得分: 1
这是使用 Blaze-Persistence Entity Views 的完美用例。
我创建了这个库,以便在 JPA 模型和自定义接口或抽象类定义的模型之间实现轻松映射,类似于功能强化版的 Spring Data Projections。核心思想是你可以根据自己的喜好定义目标结构(领域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。
如果你稍微调整了 CompanyStatus
和 CompanyStatusEmployeeStatus
实体,并添加以下内容:
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);
Blaze-Persistence Entity Views 还与 Spring Data 集成,使你几乎可以像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
英文:
This is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
If you adapt the CompanyStatus
and CompanyStatusEmployeeStatus
entities a bit and add the following:
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;
}
Your model could look like the following:
@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();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
CompanyStatusDTO c = entityViewManager.find(entityManager, CompanyStatusDTO.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
答案3
得分: 0
你可以尝试这样做:
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);
}
英文:
You can try this:
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
and you can then access like so in the service layer:
private Dao dao;
@Transactional(readOnly = true)
public List<MyEntity> getAll() {
return dao.getAll(MyEntity.class);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论