我在Media实体和MediaAnalysis实体之间存在一对一的关系,其中Media实体是抽象基类:

新闻报道实体

@Entity
@DiscriminatorValue("N")
public class NewsReport extends Media {

    @Column(name = "BODY", nullable = false)
    private String body;

    NewsReport(){}

    public NewsReport(String title, String link, String author, String body) {
        super(title, link, author);
        this.body= body;
    }

    public String getBody() {
        return body;
    }
}

媒体实体
@Entity
@Inheritance(
        strategy = InheritanceType.SINGLE_TABLE
)
@DiscriminatorColumn(name = "TYPE", length = 1, discriminatorType = DiscriminatorType.STRING)
public abstract class Media {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;

    @Column(name = "TITLE", nullable = false)
    private String title;

    @Column(name = "LINK", length = 500, nullable = false)
    private String link;

    @Column(name = "AUTHOR", length = 45, nullable = false)
    private String author;

    @OneToOne(mappedBy = "media")
    private MediaAnalysis analysis;

    Media(){}

    public Media(String title, String link, String author) {
        this.title = title;
        this.link = link;
        this.author = author;
    }

    // getters

    public Optional<MediaAnalysis> getAnalysis() {
        return Optional.ofNullable(analysis);
    }
}

媒体分析​​
@Entity
public class MediaAnalysis {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;

    @Column(name = "SUCCESS", nullable = false)
    private Boolean success;

    @OneToOne
    @JoinColumn(
            name = "MED_ID",
            nullable = false,
            foreignKey = @ForeignKey(name="MEA_MED_FK")
    )
    private Media media;

    @Column(name = "CONTENT", nullable = false)
    private String content;

    MediaAnalysis() { }

    public MediaAnalysis(Media media, Boolean success, String content) {
        this.media = media;
        this.success = success;
        this.content = content;
    }

    // getters

    public Media getMedia() {
        return media;
    }

    public String getContent() {
        return content;
    }
}

现在,当我想使用我的AnalysisRepository.getByMedia(..a NewsReport...)
public interface AnalysisRepository extends JpaRepository<MediaAnalysis,Long> {

    @Query("SELECT a FROM MediaAnalysis a LEFT JOIN FETCH a.media WHERE a.media = ?1")
    Optional<MediaAnalysis> getByMedia(Media media);

}

例如,要通过MediaAnalysis查找NewsReport,我希望hibernate运行单个SELECT查询,例如:



但是,当我启用查询日志记录时,我看到了2:



似乎首先按预期选择了MediaAnalysis,但随后又出现了另一个不必要的查询。我可以分辨出这两个查询之间的唯一区别是联接类型。我认为问题与Media继承有关。

为什么会这样呢? +我该怎么做才能确保这是一个查询?

进一步说明,如果我从存储库中删除了@Query,则实际上存在三个查询!

最佳答案

我没有JpaRepository的经验,只是(很多)关于Hibernate(主要是&CriteriaBuilder)的经验,但是有一些想法:

  • 尝试仅在两个实体之一中映射@OneToOne(在您的示例中应为MediaAnalysis)
  • 尝试将MediaAnalysis映射为1:n关系(好像每个媒体可能有多个MediaAnalysis,这在我的理解中可能是正确的,也许不在您的域中)。

  • 查看是否有任何有助于生成查询的信息。

    09-25 21:02