需求场景
有时候我们需要查询一个表中的某几个字段,或者多表 join 后各取一部分字段返回,这个时候是没有现成的 Entity 实体可以用的,但如果使用 Object[][] 数组来接受就比较难受,还得加工转换,理想情况下是直接使用 一个 Java Bean 接受
实现方式
查了一下网上发现大部分提供的例子都用不了,包括通过 GPT4 解答的乱七八糟,不得不说现阶段的AI大模型,还有待优化,最终经过测试,确定有两种方式是可以的,而且能跑的通。
spring boot 版本: 2.5.3
基于接口实现
实体类代码:接口定义所有要返回字段的getter方法即可
public interface IResult {
String getName();
String getCount();
}
Dao代码
public interface TestDao extends JpaRepository<XXX, Long> {
@Query(nativeQuery = true, value=" select a.name as name, b.count as count from t1 a, t2 b where a.id=b.id ")
List<IResult> findResult();
}
Controller直接调用即可:
@RestController
@Slf4j
public class TestController {
@Resource
private TestDao testDao;
@GetMapping("/test/getResult")
public String test(){
List<IResult> rs = testDao.findResult();
return "ok";
}
}
基于类实现
Bean DTO定义:
import javax.persistence.*;
@NamedNativeQuery(name = "TestDTO.testQueryJoinBean",
query = " select a.id as id, a.name as name, b.count as count from t1 a, t2 b where a.id=b.id",
resultSetMapping = "queryTestDTO"
)
@SqlResultSetMapping(
name = "queryTestDTO",
entities = {
@EntityResult(
entityClass = TestDTO.class,
fields = {
@FieldResult(name = "id", column = "id"),
@FieldResult(name = "name", column = "name"),
@FieldResult(name = "count", column = "count")
}
)
}
)
@Data
@Entity
public class TestDTO {
@Id
private Long id;
private String name;
private Double count;
}
Dao定义:
public interface TestDao extends JpaRepository<TestDTO, Long> {
//只要这个方法名和 DTO里面定义的NamedNativeQuery定义的name一样即可,注意是点后面的名字
List<TestDTO> testQueryJoinBean();
}
Controller查询:
@RestController
@Slf4j
public class TestController {
@Resource
private TestDao testDao;
@GetMapping("/test/getResult")
public String test(){
List<TestDTO> rs = testDao.testQueryJoinBean();
return "ok";
}
}
实现方式对比
可以看出来基于接口的方式更加优雅,不需要处理一堆映射定义,需要那个字段就加哪个字段即可,但是基于接口的缺点在于,返回的不是类实例,如果需要对返回的结果进一步进行处理必须需要新声明一个 Bean 接受处理完的数据,而基于类的就比较友好了,可以直接修改类本身的数据