使用过jpa就会知道,我们借住@Query注解进行查询操作时,如果单表查询返回的是一个字段或者一个实体类时,很容易接收查询的结果;但是如果我们进行多表关联查询,查询的字段并不一定都在一个表中,所以就不能用实体类接收了,对于这样查询结果又一下三种方式处理。
用Object[]接收 这种方式显得水平好矬,取值的时候还要通过数组索引去取值,太low了,一堆代码看起来也不好看。如果仅是做一些统计类的查询勉强可以接收。
- 用Map<String, Object>接收
这种方式相对来说要比Object[]好,因为map的key就是我们查询的字段名,再取值的时候直接通过get方法取值就行,比较方便,当是相比直接用一个pojo来接收结果,使用起来还是要差一些。如何才能将结果转成自定义的对象呢,网上有一些文章是这样处理的:先有map来接收,再讲map转成json,最后将json解析成自定义得pojo(参见JPA自定义对象接收查询结果集_klayer_cong的博客-CSDN博客)。这样看起来处理过程有点麻烦,但是比较容易理解,确实也转成了自定义的pojo,如果只是一条查询结果这样实现还说的过去,如果查询出的数量很大,将会大大影响性能,这个时候就不太好了。
- 用@NamedNativeQuery+@SqlResultSetMapping处理
具体实现如下:
(1)pojo
@NamedNativeQuery(
name = "querySummary",
query = " select t2.city_cd as cityCd,t2.city_name as cityName,DATE_FORMAT(t1.create_time,'%Y-%m-%d') as createDate,t1.sale_type as saleType " +
" from tb_project_sale t2 " +
" left join tb_project_sale_core t1 on t2.id = t1.id " +
" where t1.sale_type is not null ",
resultClass = SummaryDto.class,
resultSetMapping = "summaryMapping")
@MappedSuperclass
@SqlResultSetMapping(
name = "summaryMapping",
classes = @ConstructorResult(
targetClass = SummaryDto.class,
columns = {
@ColumnResult(name = "cityCd", type = String.class),
@ColumnResult(name = "cityName", type = String.class),
@ColumnResult(name = "createDate", type = String.class),
@ColumnResult(name = "saleType", type = String.class),
}
)
)
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class SummaryDto {
private String cityCd;
private String cityName;
private String createDate;
private String saleType;
}
(2)repository
@Repository
@Transactional
public class SummaryRpt {
@PersistenceContext
private EntityManager entityManager;
public List<SummaryDto> getSummary() {
return entityManager.createNamedQuery("querySummary")
.getResultList();
}
}
(3)测试类
@RunWith(SpringRunner.class
@SpringBootTest
public class SummaryServiceImplTest {
@Autowired
private SummaryRpt summaryRpt;
@Test
public void test() {
List<SummaryDto> list = summaryRpt.getSummary();
return;
}
}
注意:上文中pojo中的注解都是有用的,不要随意删减