将从 Hibernate Native Query 返回的值映射到模型
Posted
技术标签:
【中文标题】将从 Hibernate Native Query 返回的值映射到模型【英文标题】:Map values returned from Hibernate Native Query to a model 【发布时间】:2020-05-22 17:57:58 【问题描述】:我对 Hibernate 很陌生。我将它与我的 Spring Boot 项目一起使用。由于涉及复杂的连接,我想编写本机 SQL 查询。 在执行查询时,返回的值是列表的形式,没有简单的方法将它们映射到 HashMap。
现在我正在使用以下方法,该方法有效,但在很大程度上取决于从查询列表返回的值的顺序。
有没有简单有效的方法来映射这个结果。
道
@Transactional
public List<Object> getAllUsers()
Session currentSession = entityManager.unwrap(Session.class);
String queryString = "select ts.id as id, ts.remarks, concat(s.first_name, ' ',s.last_name) as studentName,\n" +
"ts.start_date as startDate, ts.end_date as endDate, ts.status,\n" +
"ts.created_at as createdAt, ts.created_by as createdBy, \n" +
"ts.updated_at as updatedAt, ts.updated_by as updatedBy\n" +
"from TRN_STATUS ts join types lt on ts.type_id = lt.id join users s on s.id = ts.id \n" +
"join category ct on ts.cat_id = ct.id\n" +
"where ts.tenant_id = 1";
NativeQuery query = currentSession.createNativeQuery(queryString);
List<Object> result = (List<Object>) query.getResultList();
currentSession.close();
return result;
服务
public List<Map<String, Object>> getCount(Optional<String> userId, String userType, String limit, String offset)
List<Object> users= userDAO. getAllUsers();
List<Map<String, Object>> userList = new ArrayList<>();
Iterator userItr = users.iterator();
ObjectMapper userMapper = new ObjectMapper();
Map<String, Object> map;
UserModel obj = new UserModel();
while(userItr.hasNext())
Object[] resobj = (Object[]) leaveItr.next();
obj.setId(String.valueOf(resobj[0]));
obj.setStartDate(String.valueOf(resobj[1]));
obj.setEndDate(String.valueOf(resobj[2]));
obj.setDescription(String.valueOf(resobj[3]));
obj.setLeaveType(String.valueOf(resobj[4]));
obj.setCategoryId(String.valueOf(resobj[5]));
obj.setCategoryName(String.valueOf(resobj[6]));
obj.setStatus(String.valueOf(resobj[7]));
obj.setDesignation(String.valueOf(resobj[8]));
obj.setActionBy(String.valueOf(resobj[9]));
obj.setStudentName(String.valueOf(resobj[10]));
obj.setImgUrl(String.valueOf(resobj[11]));
map = userMapper.convertValue(obj, Map.class);
userList.add(map);
logger.info("Value displayed was: "+ map);
return userList;
用户模型
import lombok.Data;
public @Data class UserModel
private String id;
private String startDate;
private String endDate;
private String description;
private String leaveType;
private String categoryId;
private String categoryName;
private String status;
private String designation;
private String actionBy;
private String studentName;
private String imgUrl;
private String createdDate;
private String hostelName;
private String blockName;
private String roomName;
【问题讨论】:
【参考方案1】:有一种简单有效的方法来映射此结果
与其创建一个方法,然后将所需的返回值映射到一个 bean 类,只需创建一个 Entity 类,其中包含与查询中返回的字段映射的所有字段。
使用@NamedNativeQuery 提供查询,使用@SqlResultSetMapping 映射执行查询后要返回的字段。
例如
@NamedNativeQuery(
name = "getTenders",
query = "SELECT t.id, t.created_at, CONCAT(u.first_name, ' ' , u.last_name) as created_by, t.modified_at, CONCAT(u2.first_name, ' ' , u2.last_name) as modified_by, t.tenders_abbreviation, t.tenders_full_name FROM abc.tenders v\n" +
"LEFT JOIN abc.users u on u.id = v.created_by LEFT JOIN rbac.users u2 on u2.id = v.modified_by",
resultSetMapping = "tendersMappings"
)
@SqlResultSetMapping(name = "tendersMappings", entities =
@EntityResult(entityClass = TendersEntity.class, fields =
@FieldResult(name = "id", column = "id"),
@FieldResult(name = "created_at", column = "created_at"),
@FieldResult(name = "modified_at", column = "modified_at"),
@FieldResult(name = "tenders_abbreviation", column = "tenders_abbreviation"),
@FieldResult(name = "tenders_full_name", column = "tenders_full_name"),
@FieldResult(name = "created_by", column = "created_by"),
@FieldResult(name = "modified_by", column = "modified_by")
)
)
@Entity
@Table(name = "tenders", schema = "abc")
public class TendersEntity
private static final long serialVersionUID = 1L;
@Id
private Integer id;
@Column(name = "created_at")
private String created_at;
@Column(name = "created_by")
private String created_by;
@Column(name = "modified_at")
private String modified_at;
@Column(name = "modified_by")
private String modified_by;
@Column(name = "tenders_abbreviation")
private String tenders_abbreviation;
@Column(name = "tenders_full_name")
private String tenders_full_name;
public TendersEntity()
// setters and getters
//DAO类
@Repository
@Transactional
public class TendersDaoImpl implements TendersDao
@Autowired
EntityManager manager;
@Override
public List<TendersEntity> getVendors()
List<TendersEntity> dataList = new ArrayList<>();
Query query = manager.createNamedQuery("getTenders");
try
dataList.addAll(query.getResultList());
catch (Exception ex)
…….// exception code
return dataList;
【讨论】:
你有 @Table(name = “tenders”, schema = “abc”) 即有一个表。但 sql 是多个表的连接。映射是如何发生的? 这里的招标是基表,映射是根据查询返回的数据完成的【参考方案2】:您可以为此使用 SQL 转换器:
使用原生 sql 返回非实体 bean 或 Map 通常比基本的 Object[] 更有用。使用结果转换器是可能的。
示例:
List resultWithAliasedBean = s.createSQLQuery(
"SELECT st.name as studentName, co.description as courseDescription " +
"FROM Enrolment e " +
"INNER JOIN Student st on e.studentId=st.studentId " +
"INNER JOIN Course co on e.courseCode=co.courseCode")
.addScalar("studentName")
.addScalar("courseDescription")
.setResultTransformer( Transformers.aliasToBean(StudentDTO.class))
.list();
StudentDTO dto =(StudentDTO) resultWithAliasedBean.get(0);
参考: https://docs.jboss.org/hibernate/core/3.3/reference/en/html/querysql.html#d0e13904
【讨论】:
StudentDTO的内容是什么? 在你的情况下,它将是 UserModel。以上是关于将从 Hibernate Native Query 返回的值映射到模型的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate中的query.setFirstResult(),query.setMaxResults();
hibernate里‘query’和‘ Criteria’分别啥时候用
有啥方法可以将从 APISAUCE API 收到的响应存储到异步存储中作为缓存并在 React Native 的平面列表中显示