Problem
I only care about the IDs for the associations. I do not want the DTO to have the respective associated class as an attribute. I want Parent
to have Set<String> childIds
and Child
to have String parentId
in the DTOs. Because of this, I do not want to load the entire object in the persistence layer just to map away everything else.
Attempts
EntityManager.getReference
but that throws an error if it's a new entity, so how can I save new ones? I'd have to do an existsById
but now we're making even more database calls, this is getting expensiveJoinColumn
, JoinColumns
, JoinTable
, etc.Java classes
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
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
@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
@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. I recommend you take a look at whatBlaze-Persistence Entity Views has to offer.
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.
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:
@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.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.