用spring data jpa实现单表/联表查询自定义部分字段

为什么80%的码农都做不了架构师?>>>   hot3.png

有时候不想放弃jpa持久化的便利性,又不想因此牺牲了查询的灵活性,所以列举两种jpa下的灵活查询方式。

  • 单表查询指定Entity中的部分字段

这块比较简单,只需要定义一个存放部分属性的类,包含全部参数的构造函数的必须有的

@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrginfoDTO {
	String orgcode;
	String orgname;
}

然后在repository中定义接口

	@Query("select new com.xxx.domain.OrginfoDTO(t1.orgcode, t1.orgname) from Orginfo t1")
	Page findAllDTO(Pageable pageable);

测试这个方法,日志中会打出sql,只会查询指定的那几个字段,而jpa默认的不是select *

Hibernate: select t1.orgcode, t1.orgname from Orginfo t1 limit 10 offset 0

 

  • 联表查询多个Entity中的关联字段

由于现在的项目基本不会用到外键,所以也没有在jpa中设置@ManyToOne,@ManyToMany等关联注解,

所有的Entity中的属性都基本类型,没有任何关联关系,这的确防止jpa自动在表中生成外键,

但是由此带来的字段翻译呈现是个痛点,如何用spring data jpa实现联表查询呢,

下面的DTO中包含了两张表中的字段,Orginfo中有areacode,Areainfo表中有地区名称

@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrginfoDTO {
	String orgcode;
	String orgname;
	String areaname;
}

 然后在Orginfo这个Entity中声明你的结果DTO,并在@NamedNativeQuery中写好的你本地查询sql

import javax.persistence.ColumnResult;
import javax.persistence.ConstructorResult;
import javax.persistence.Entity;
import javax.persistence.NamedNativeQuery;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.Table;

@SqlResultSetMapping(
        name = "OrginfoDTO", 
		classes = {
                @ConstructorResult(
                        targetClass = OrginfoDTO.class,
                        columns = {
                                @ColumnResult(name = "orgcode", type = String.class),
                                @ColumnResult(name = "orgname", type = String.class),
                                @ColumnResult(name = "areaname", type = String.class)
                        }
                )
        }
)
@NamedNativeQuery(
        name = "Orginfo.findAllDTONative",
        query = "select t1.orgcode, t1.orgname, t2.name as areaname from Orginfo t1, Areainfo t2 where t1.areacode = t2.code and t1.orgtype = :orgtype limit 10 offset 0",
        resultSetMapping = "OrginfoDTO"
)
@Slf4j
@Entity
@Table(name="orginfo")
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper=true)
@NoArgsConstructor
public class Orginfo {
...
}

接着写repository中的接口,接口中的方法名称必须与@NamedNativeQuery中的name对应,同时nativeQuery必须声明为true,不然它会认为你执行的不是native sql而是hql

	@Query(nativeQuery=true)
	List findAllDTONative(@Param("orgtype") Integer orgtype);

下面我们执行以下单元测试,看下日志是否如我们所期望的

Hibernate: select t1.orgcode, t1.orgname, t2.name as areaname from Orginfo t1, Areainfo t2 where t1.areacode = t2.code and t1.orgtype = ? limit 10 offset 0
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : native totals: 10
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310240099, orgname=21085684341, areaname=杭州市)
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310215099, orgname=测试账户, areaname=杭州市)
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310246099, orgname=绍兴市雪花机电有限公司1, areaname=绍兴市)
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310236091, orgname=北京中全清茂展览展示有限公司IWW, areaname=杭州市)
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310231091, orgname=电子同城联调六, areaname=杭州市)
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310230091, orgname=test, areaname=杭州市)
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310224091, orgname=杭州光大测试2, areaname=杭州市)
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310223099, orgname=测试专用对公1, areaname=杭州市)
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310248091, orgname=孙悟空, areaname=宁波市)
2017-12-05 15:01:56.286  INFO 12540 --- [           main] c.e.o.domain.OrginfoRepositoryTest       : OrginfoDTO(orgcode=3310216099, orgname=业务测试有限公司53069, areaname=杭州市)

的确联表只查询了所需要的三个字段,并且组装到dto中成功输出。

转载于:https://my.oschina.net/buwei/blog/1585088

你可能感兴趣的:(用spring data jpa实现单表/联表查询自定义部分字段)