带有Projection和List的Spring Data JPA Query创建了无效的SQL

时间:2018-04-10 18:16:00

标签: mysql hibernate spring-data-jpa

我试图使用JPA查询和投影仅检索某一部分数据。这是查询:

@Repository
public interface CompanyRepository extends CrudRepository<Company, Integer> {
    @Query("select co.companyID as companyid, co.companyName as companyname, co.companyAbbr as companyabbr, co.flags as flags from Company co order by companyName asc")
    List<CompanyWithFlags> getAllCompaniesWithFlags();
}

以下是投影:

public interface CompanyWithFlags {
    Integer getCompanyid();
    String getCompanyname();
    String getCompanyabbr();
    List<CompanyFlag> getFlags();
}

以下是公司实体:

@Entity
@Table(name="companies.companies")
public class Company implements Serializable {
    private static final long serialVersionUID = 1L;

    private int companyID;
    private String companyName;
    private String companyAbbr;
    ...
    private List<CompanyFlag> flags = new ArrayList<>();

    public Company() {}

    @Id
    @Column(name="pk_companyid")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonView(View.AllCompaniesView.class)
    public int getCompanyID() {
        return companyID;
    }

    public void setCompanyID(int companyID) {
        this.companyID = companyID;
    }

    @Column(name="companyname", columnDefinition="VARCHAR(72)")
    @JsonView(View.AllCompaniesView.class)
    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    @Column(name="companyabbr", columnDefinition="VARCHAR(8)")
    @JsonView(View.AllCompaniesView.class)
    public String getCompanyAbbr() {
        return companyAbbr;
    }

    public void setCompanyAbbr(String companyAbbr) {
        this.companyAbbr = companyAbbr;
    }

    ...

    @ManyToMany(fetch=FetchType.LAZY)
    @JoinTable(name="companies.co_flags",
               joinColumns = @JoinColumn(name="fk_companyid", referencedColumnName="pk_companyid"),
               inverseJoinColumns = @JoinColumn(name="fk_flagid", referencedColumnName="pk_flagid"))
    @JsonView(View.AllCompaniesView.class)
    public List<CompanyFlag> getFlags() {
        return flags;
    }

    public void setFlags(List<CompanyFlag> flags) {
        this.flags = flags;
    }
}

如果我将CompanyFlag退出查询和投影,一切正常。如果我不编写查询,而只是使用:

List<CompanyWithFlags> findAllByOrderByCompanyNameAsc();

然后我根据需要获取数据,但是也会生成很长的其他(不必要的)查询列表。

实际上,hibernate(5.2.14)生成了这个查询:

select 
  company0_.pk_companyid as col_0_0_, 
  company0_.companyname as col_1_0_, 
  company0_.companyabbr as col_2_0_, 
  . as col_3_0_, 
  companyfla2_.pk_flagid as pk_flagi1_9_, 
  companyfla2_.fk_categoryid as fk_categ3_9_, 
  companyfla2_.flagname as flagname2_9_ 
from companies.companies company0_ 
inner join companies.co_flags flags1_ on company0_.pk_companyid=flags1_.fk_companyid 
inner join companies.config_flags companyfla2_ on flags1_.fk_flagid=companyfla2_.pk_flagid 
order by companyName asc

显然,问题是. as col_3_0_,但我无法弄清楚为什么要生成它或如何摆脱它。任何人都可以解释为什么hibernate会在存储库中添加这些以及我可以做些什么来以有效的方式实现所需的数据?谢谢!

2 个答案:

答案 0 :(得分:0)

它似乎是Spring Data JPA中的一个错误 - 请参阅我的报告:DATAJPA-1299

要解决此问题,请尝试使用带有&#39; distinct&#39;的查询方法。如下:

@EntityGraph(attributePaths = "flags")
List<CompanyWithFlags> findDistinctAllByOrderByCompanyNameAsc();

答案 1 :(得分:0)

我终于能够找到一个有效的查询,虽然不像我预期的那样。这是查询:

if annotation is MKPointAnnotation {

    let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "Online")
    annotationView.image = rotatedArrow
    annotationView.canShowCallout = true

    return annotationView

}

我想要/希望得到格式为的结果:

@Query("select co.companyID as companyid, co.companyName as companyname, co.companyAbbr as companyabbr, fl as flags from Company co left join co.flags fl order by companyName asc")
List<CompanyWithFlags> getAllCompaniesWithFlags();

但是,查询会产生如下结果:

companyid: 1,
companyabbr: "ABC",
companyname: "Alpha Beta Company",
flags: [
  {
    flagID: 1,
    flagName: "Flag 1"
  },
  {
    flagID: 2,
    flagName: "Flag 2"
  }
]

我在前端使用Angular,它能够正确读取这个以达到我想要的最终结果,所以这个查询对我有用。它在Hibernate中产生最少量的SQL查询。