JPA一对一映射与继承:2查询应该是什么

Edd*_*Edd 5 spring hibernate jpql spring-data-jpa

我在实体是一个抽象基类的实体MediaMediaAnalysis实体之间有一对一的关系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;
    }
}
Run Code Online (Sandbox Code Playgroud)

媒体实体

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

媒体分析

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当我想用​​我的 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);

}
Run Code Online (Sandbox Code Playgroud)

要找到一个MediaAnalysisNewsReport例如我希望冬眠跑单SELECT的查询,是这样的:

从媒体分析m中选择m.*,其中m.med_id =?

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

DEBUG ohSQL:92 - 选择mediaanaly0_.id为id1_0_0_,media1_.id为id2_1_1_,mediaanaly0_.med_id为med_id3_0_0_,mediaanaly0_.success为success2_0_0_,media1_.author为author3_1_1_,media1_.link为link4_1_1_,media1_.title为title5_1_1_,media1_. body as body6_1_1_,media1_.type as type1_1_1_ from mea_media_analysis mediaanaly0_ left outer join med_media media1_ on mediaanaly0_.med_id = media1_.id where mediaanaly0_.med_id =?

TRACE ohtdsBasicBinder:65 - 绑定参数[1]为[BIGINT] - [1]

DEBUG ohSQL:92 - 选择mediaanaly0_.id为id1_0_1_,mediaanaly0_.med_id为med_id3_0_1_,mediaanaly0_.success为success2_0_1_,media1_.id为id2_1_0_,media1_.author为author3_1_0_,media1_.link为link4_1_0_,media1_.title为title5_1_0_,media1_. body as body6_1_0_,media1_.type as type1_1_0_ from mea_media_analysis mediaanaly0_ inner join med_media media1_ on mediaanaly0_.med_id = media1_.id where mediaanaly0_.med_id =?

TRACE ohtdsBasicBinder:65 - 绑定参数[1]为[BIGINT] - [1]

它似乎首先选择了MediaAnalysis预期的,但是还有一个其他查询似乎是不必要的.我可以在这两个查询之间区分的唯一区别是连接类型.我认为这个问题与Media继承有关.

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


另外请注意,如果我@Query从我的存储库中删除了实际上有三个查询!

DEBUG ohSQL:92 - 选择mediaanaly0_.id为id1_0_,mediaanaly0_.med_id为med_id3_0_,mediaanaly0_.success为success2_0_来自mea_media_analysis mediaanaly0_ left outer join med_media media1_ on mediaanaly0_.med_id = media1_.id其中media1_.id =?

TRACE ohtdsBasicBinder:65 - 绑定参数[1]为[BIGINT] - [1]

DEBUG ohSQL:92 - 选择media0_.id为id2_1_0_,media0_.author为author3_1_0_,media0_.link为link4_1_0_,media0_.title为title5_1_0_,media0_.body为body6_1_0_,media0_.type为type1_1_0_,mediaanaly1_.id为id1_0_1_,mediaanaly1_. med_id为med_id3_0_1_,mediaanaly1_.success为success2_0_1_来自med_media media0_ left outer join mea_media_analysis mediaanaly1_ on media0_.id = mediaanaly1_.med_id其中media0_.id =?

TRACE ohtdsBasicBinder:65 - 绑定参数[1]为[BIGINT] - [1]

DEBUG ohSQL:92 - 选择mediaanaly0_.id为id1_0_1_,mediaanaly0_.med_id为med_id3_0_1_,mediaanaly0_.success为success2_0_1_,media1_.id为id2_1_0_,media1_.author为author3_1_0_,media1_.link为link4_1_0_,media1_.title为title5_1_0_,media1_. body as body6_1_0_,media1_.type as type1_1_0_ from mea_media_analysis mediaanaly0_ inner join med_media media1_ on mediaanaly0_.med_id = media1_.id where mediaanaly0_.med_id =?

TRACE ohtdsBasicBinder:65 - 绑定参数[1]为[BIGINT] - [1]

小智 1

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

  • 尝试@OneToOne仅映射两个实体之一(根据您的示例应该是 MediaAnalysis)
  • 尝试映射MediaAnalysis为 1:n 关系(就好像MediaAnalysis每个媒体可以有多个,这很可能符合我的理解,只是可能不在您的领域中)。

看看其中是否有任何有助于生成的查询。