简体   繁体   English

如何在 Spring JPA/Hibernate 中使用 JoinTable 仅通过 ID 设置引用父实体的子实体

[英]How to set up a child entity referencing parent by only ID using a JoinTable in Spring JPA/Hibernate

Problem问题

  1. I have a parent entity with a one-to-many relationship with child entities.我有一个与子实体具有一对多关系的父实体。
  2. Mapstruct is being used to map entities to DTOs, so just fetching all (even lazily) will result in every instance being instantiated/fetched from persistence (which we do not want, I only care about IDs outside of the Spring JPA/Hibernate classes) Mapstruct 用于将实体映射到 DTO,因此仅获取所有(甚至懒惰)将导致每个实例从持久性中实例化/获取(我们不希望如此,我只关心 Spring JPA/Hibernate 类之外的 ID)
  3. Both parent and child's tables have no reference of the other, the relationship is handled by a join table父子表互不引用,关系由连接表处理

I only care about the IDs for the associations.我只关心关联的 ID。 I do not want the DTO to have the respective associated class as an attribute.我不希望 DTO 将相应的关联类作为属性。 I want Parent to have Set<String> childIds and Child to have String parentId in the DTOs.我希望Parent在 DTO 中有Set<String> childIdsChildString parentId Because of this, I do not want to load the entire object in the persistence layer just to map away everything else.因此,我不想在持久层中加载整个对象只是为了映射其他所有内容。

Attempts尝试

  1. Having the entity classes reference the other entity class.让实体类引用另一个实体类。 Entity → DTO is ok , but DTO → Entity Hibernate/Spring JPA complains that the entity is detached (because it just came from an ID).实体→DTO是好的,但DTO→实体的Hibernate / JPA春抱怨的实体分离(因为它只是从ID来)。 One solution I thought of is calling EntityManager.getReference but that throws an error if it's a new entity, so how can I save new ones?我想到的一种解决方案是调用EntityManager.getReference但如果它是一个新实体,则会引发错误,那么我该如何保存新实体呢? I'd have to do an existsById but now we're making even more database calls, this is getting expensive我必须做一个existsById但现在我们要进行更多的数据库调用,这变得越来越昂贵
  2. A bunch of combinations of JoinColumn , JoinColumns , JoinTable , etc.一堆JoinColumnJoinColumnsJoinTable等的组合。

Java classes Java 类

Entities实体

@Entity
@(LombokGettersAndSetters)
public class ParentEntity {
    
    @Id
    private Long id;
    
    @(???)
    private Set<Long> childIds; || private Set<ChildEntity> children;
}
@Entity
@(LombokGettersAndSetters)
public class ChildEntity {
    
    @Id
    private Long id;

    @(???)
    private Long parentId; || private ParentEntity parent;
}

Mappers映射器

(Mapstruct mappers)

DTOs DTO

public class ParentDTO {
    private Long id;
    private Set<Long> childIds;
}
public class ChildDTO {
    private Long id;
    private Long parentId;
}

Tables

Parent       Child      Parent_join_Child
-------      -----      -----------------
id           id         parent_id
                        child_id

Thanks in advance!提前致谢!

Edit @ +1m : I should note, I removed some annotations in my examples such as the below编辑@ +1m :我应该注意,我在我的示例中删除了一些注释,如下所示

@Column(name = "parent_id", columnDefinition = CustomColumnDefinition.UNSIGNED_INT)
@GeneratedValue(strategy = GenerationType.IDENTITY)

You can use @JoinTable to join your parent to child as shown below您可以使用@JoinTable将您的父母加入到孩子中,如下所示

@Entity
@(LombokGettersAndSetters)
public class ParentEntity {
    
    @Id
    private Long id;
    
    @JoinTable(name = "Parent_join_Child", joinColumns = {
            @JoinColumn(name = "parent_id", referencedColumnName = "id") }, inverseJoinColumns = {
                    @JoinColumn(name = "child_id", referencedColumnName = "id") })
    private Set<ChildEntity> children;
}

Can you do the following:你能不能做到以下几点:

Create ParentChild entity:创建父子实体:

@Entity
public class ParentChild {
  
  private long id;
  private long parentId;
  private long childId;

}

and work with it:并使用它:

   parentChildRepository.findByWhatever() and group by parent and map to dto.

You'd have to write a custom query that selects only the parts that you care about, but then you won't be able to use Mapstruct.您必须编写一个仅选择您关心的部分的自定义查询,但是您将无法使用 Mapstruct。 I recommend you take a look at whatBlaze-Persistence Entity Views has to offer.我建议您查看Blaze-Persistence Entity Views提供的功能。

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.我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义的模型之间轻松映射,例如类固醇上的 Spring Data Projections。 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.这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

Assuming an entity model like this:假设一个实体模型是这样的:

@Entity
public class ParentEntity {
    
    @Id
    private Long id;
    
    @OneToMany(mappedBy = "parent")
    private Set<ChildEntity> children;
}

@Entity
public class ChildEntity {
    
    @Id
    private Long id;

    @ManyToOne
    private ParentEntity parent;
}

A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:

@EntityView(ParentEntity.class)
public interface ParentDTO {
    @IdMapping
    Long getId();
    @Mapping("children.id")
    Set<Long> getChildIds();
}

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.查询是将实体视图应用于查询的问题,最简单的只是按 id 查询。

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

Behind the scenes this will create the query to fetch exactly what is needed, nothing more.在幕后,这将创建查询以准确获取所需内容,仅此而已。

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 Spring Data 集成允许您几乎像 Spring Data Projections 一样使用它: https : //persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 Spring JPA DATA 仅获取特定的子实体及其具有特定值的父实体 - How to fetch only the specific child entity along with its Parent entities with specific value using Spring JPA DATA 如何使用 Lombok 在 Spring/JPA/Hibernate 中获取带有所有子实体和子实体的父实体 - How to get parent entity with all child entities and child entities of children in Spring/JPA/Hibernate with Lombok Hibernate JPA持久保存具有空父ID的子实体 - Hibernate JPA persist saved child entity with null parent id Hibernate JPA joinTable共享ID - Hibernate JPA joinTable share ID 如何从 Hibernate Jpa 中的父实体仅获取 ChildIds(而不是整个子对象)? - How to get only ChildIds(Instead of whole child Object) from parent entity in Hibernate Jpa? 如何通过JPA / Hibernate在孩子的ID中引用父母的ID? - How to reference a parent's id in a child's id with JPA/Hibernate? JPA如何通过只读取外键值来设置JoinTable关系 - JPA how to set up JoinTable relationship by reading only foreign key value 如何使用 spring 数据 JPA 为现有父实体添加子实体? - How to add child entity for existing parent entity using spring data JPA? 如何使用子实体检索父实体-Spring数据JPA - How to retrieve parent entity using child entity-Spring data JPA JPA / Hibernate - 在子更改时更新父实体 - JPA / Hibernate - Update parent entity on child changes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM