spring data 返回任意字段
在spring boot + spring data查询数据库的过程中,有时候总会出现一些复杂的查询,我们希望数据库返回的字段能随意改变。这个需求在mybatis里很好解决,只需要用map接收就可以,但在用spring data的时候有些麻烦。今天来讨论一下可选的方案。基于spring boot 1.5.15.RELEASE 和 2.2.1.RELEASE。
spring boot 版本 1.5.15.release
一、官方推荐的做法interface-based Projections 和 class-based Projections
interface-based Projections
1、根据数据库要返回的字段,建立一个interface,实现各个字段的get方法
interface SomeDto{ Long getId(); String getName(); Date getCreateTime(); }
2、在repository中,写nativeQuery查询,并以上面新建的interface作为返回对象
@Query(nativeQuery=true,value="SELECT id,name,create_time FROM table") List<SomeDto> find();
3、spring boot会把查询的结果集的每一条记录,对应到SomeDto中,并为其创建一个代理对象(proxy instance)。然后你可以将其当作一般对象,从里面获取数据。
List<SomeDto> dtoList = repository.find(); String name1 = dtoList.get(0).getName(); System.out.println(name1);
class-based Projections
上述查询方式,根据官方文档,也可以基于普通的class。但是我在尝试的过程中,总是报错,放弃。
参考
1、https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.dtos(5.3.11.Projections)
2、https://stackoverflow.com/questions/29082749/spring-data-jpa-map-the-native-query-result-to-non-entity-pojo?r=SearchResults
其他方式,可行但不推荐的方式
二、在repository中写sql,返回Object[]
@Query(nativeQuery=true, value = "SELECT id,name,create_time FROM table") List<Object[]> find();
返回的结果集的每一条记录,都是一个Object[],数组的0、1、2。。。等位置分别顺序对应查询的字段。
三、在repository中写hql,返回Map
@Query(nativeQuery=false, value = "SELECT new map(id,name,create_time) FROM table") List<Map> findSome();
查询用了hql,如果是简单查询还好。如果涉及多表联查或是聚合函数,还需要查hql的对应语法,很麻烦。
而且,表面上,返回的是Map,其实它还是一个Object[],因为map的key不是数据库字段,而是数组下标。
四、使用EntityManager,
String sql = "SELECT id,name,create_time FROM table"; Query query = entityManager.createNativeQuery(sql); query.unwrap(SQLQuery.class).setResultTransformer(Transformer.ALIAS_TO_ENTITY_MAP); List<Map> list = query.getResultList();
这个方法,可以正常的将sql查询结果转换成map,并且map的key就是数据库查询的字段的名字。然而需要使用entityManager,不能直接在repository中写sql,写法非常啰嗦。
spring boot 版本 2.2.1.RELEASE
1、此版本的spring data,在repository中进行nativeQuery sql查询,可以直接将,查询字段映射到map,并且map的key就是数据库的字段。
@Query(nativeQuery=true, value = "SELECT id,name,create_time FROM table") List<Map<String,Object>> find();
List<Map<String,Object>> list = repository.find(); String name1 = list.get(0).get("name"); System.out.println(name1);