带有或不带有JPA的代表同一张表的不同实体 [英] Different entities representing the same table, with and without joins, with JPA

查看:68
本文介绍了带有或不带有JPA的代表同一张表的不同实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理具有许多联接的数据库.我想要一些由两个或多个不同实体表示的表,带有或不带有联接.这是一个简化的示例:

I'm working with a database with many joins. I'd like to have some tables represented by two or more different entities, with and without joins. This is a simplified example:

具有联接的版本

@Entity
@Table(name = "books")
public class Book{

    @Id
    private Integer id;

    @Column(name = "title")
    private String title;

    @ManyToOne
    @JoinColumn(name = "author_id", foreignKey = @ForeignKey(name = "id"))
    private @NotNull Author author; // the class Author is an entity for the table "authors"

}

无连接版本

@Entity
@Table(name = "books")
public class BookWithDetails{

    @Id
    private Integer id;

    @Column(name = "title")
    private String title;

    @Column(name = "author_id")
    private Integer authorId;

}

我想构建一个API,该API仅在需要时才允许检索细节.例如:

I want to build an API that allows me to retrieve the details only when I need them. For example:

/api/books/123

{
  "id": 123,
  "title": "The Lord of the Rings",
  "authorId": 321
}

/api/books/123/details

{
  "id": 123,
  "title": "The Lord of the Rings",
  "author": {
    "name": "John Ronald Reuel",
    "surname": "Tolkien"
  }
}

理想的解决方案是让BookWithDetails扩展Book,并且在书/作者示例中,让Author author替换Integer authorId(但也可以同时使用).

The ideal solution would be having BookWithDetails extend Book and, in the book/author example, having the Author author replacing Integer authorId (but having both would be fine too).

我无法使用它,因为两个实体都引用同一张表,并且Hibernate自动搜索不存在的dtype判别列.

I can't get this to work as both entities refer to the same table and Hibernate automatically search for a dtype discriminant column which does not exist.

我搜索了类似的问题并尝试了许多解决方案,但都不满足我的需求,主要是因为它们需要使用区分列或有关共享公共字段的不同表.

I searched for similar questions and tried many solutions but none of them fit my needs, mostly because they require the use of a discriminator column or they are about different tables sharing common fields.

有什么想法吗?

推荐答案

让多个实体引用同一张表不是一个好主意.您可以利用Hibernate提供的不可变实体概念,但这只会使您受益匪浅.

It's not a good idea to have multiple entities referring to the same table. You can make use of the immutable entity concept Hibernate offers, but that will only get you that far.

我认为这是 Blaze-Persistence实体视图.

我创建了该库,以允许在JPA模型与自定义接口或抽象类定义的模型之间轻松进行映射,例如类固醇上的Spring Data Projections.这个想法是,您可以按自己喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(获取器)映射到实体模型.

I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.

针对您的用例的DTO模型可能与Blaze-Persistence Entity-Views相似,如下所示:

A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:

@EntityView(Books.class)
public interface BookWithoutDetails {
    @IdMapping
    Integer getId();
    String getTitle();
    @Mapping("author.id")
    Integer getAuthorId();
}

@EntityView(Books.class)
public interface BookWithDetails {
    @IdMapping
    Integer getId();
    String getTitle();
    AuthorDto getAuthor();
    @EntityView(Author.class)
    interface AuthorDto {
        @IdMapping
        Long getId();
        String getName();
    }
}

查询是将实体视图应用于查询的问题,最简单的方法就是按ID查询.

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.

BookWithDetails a = entityViewManager.find(entityManager, BookWithDetails.class, id);

Spring Data集成使您可以像使用Spring Data Projections一样使用它:

The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

List<BookWithDetails> findAll();

这篇关于带有或不带有JPA的代表同一张表的不同实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆