带有额外列和嵌入式 ID 的 Spring JPA 多对多

问题描述 投票:0回答:1

我有一个模型多次与其他两个实体建立多对多关系,当我尝试保存它们时出现堆栈溢出错误。尝试了一堆解决方案,阅读了一堆文章,甚至在这里找到了答案,但都没有奏效。由于他们中的很多人真的很老,所以我决定发布这个问题。

我的关系是“Profile”有多个“Stat”和多个“Interest”,所以一个 Profile 可以有多个 Stats,一个 Stat 可以在多个 Profiles 中,因此一个 Profile 可以有多个 Interests,一个 Interest 可以在多个 Profiles .基于此,我创建了类“ProfileStat”和“ProfileInterest”,它们分别将“ProfileStatId”和“ProfileInterestId”作为 IDClass,如下所示: 简介类

@Entity
public class Profile extends GenericEntity {

    @Column(nullable = false, length = 100)
    private String name;

    @OneToOne(mappedBy = "stat", cascade = CascadeType.ALL, orphanRemoval = true)
    private ProfileStat smokes;

    @OneToMany(mappedBy = "stat", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<ProfileStat> languages;

    @OneToMany(mappedBy = "interest", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<ProfileInterest> relationshipInterests;
}

ProfileStat 类

@Entity
public class ProfileStat {

    @EmbeddedId
    private ProfileStatId profileStatId = new ProfileStatId();

    @ManyToOne
    @MapsId("statId")
    @JoinColumn(name = "stat_id")
    private Stat stat;

    @ManyToOne
    @MapsId("profileId")
    @JoinColumn(name = "profile_id")
    private Profile profile;

    @Column
    private boolean displayable;
}

ProfileStatId 类

@Embeddable
public class ProfileStatId implements Serializable {

    private static final long serialVersionUID = 1L;

    private UUID statId;

    private UUID profileId;
}

简介兴趣班

@Entity
public class ProfileInterest {

    @EmbeddedId
    private ProfileInterestId profileInterestId = new ProfileInterestId();

    @ManyToOne
    @MapsId("interestId")
    @JoinColumn(name = "interest_id")
    private Interest interest;

    @ManyToOne
    @MapsId("profileId")
    @JoinColumn(name = "profile_id")
    private Profile profile;

    @Column
    private boolean displayable;
}

ProfileInterestId 类

@Embeddable
public class ProfileInterestId implements Serializable {

    private static final long serialVersionUID = 1L;

    private UUID interestId;

    private UUID profileId;
}

在那之后,我有一个端点成功保存了没有统计和兴趣的配置文件,但是,当我尝试保存统计和兴趣时,它给了我一个堆栈溢出异常。我保存配置文件,然后立即创建 Stats 和 Interests 实例,但它甚至无法完成对象的创建,更不用说保存它们了。创建这些对象的方法如下所述:

public Profile enrichProfile(Profile profile, ProfileDTO profileDTO) throws RestRequestException {

    // There's some code here that works, the problem is with the next line

    profile.setLanguages(buildProfileStat(findStats(profileDTO.getLanguages()), profile));        
    profile.setRelationshipInterests(buildProfileInterest(findInterests(profileDTO.getRelationshipInterestsId()), profile));
    return profile;
}

private Set<ProfileStat> buildProfileStat(Collection<Stat> stats, Profile profile) {
    Set<ProfileStat> profileStats = new HashSet<>();
    for(Stat stat : stats) {
        profileStats.add(new ProfileStat(stat, profile, false));
    }
    return profileStats;
}

private Set<Stat> findStats(Collection<UUID> ids) throws RestRequestException {
    Set<Stat> stats = new HashSet<>();
    for (UUID id : ids) {
        stats.add(statService.findById(id)
                .orElseThrow(() -> new RestRequestException(HttpStatus.NOT_FOUND, ErrorIndicator.ERROR_CPRAPI_0012_D.getMessage())));
    }
    return stats;
}

private Set<ProfileInterest> buildProfileInterest(Collection<Interest> interests, Profile profile) {
    Set<ProfileInterest> profileInterest = new HashSet<>();
    for(Interest interest : interests) {
        profileInterest.add(new ProfileInterest(interest, profile, false));
    }
    return profileInterest;
}

private Set<Interest> findInterests(Collection<UUID> ids) throws RestRequestException {
    Set<Interest> interests = new HashSet<>();
    for (UUID id : ids) {
        interests.add(interestService.findById(id)
                .orElseThrow(() -> new RestRequestException(HttpStatus.NOT_FOUND, ErrorIndicator.ERROR_CPRAPI_0012_E.getMessage())));
    }
    return interests;
}

这就是我在 Profile 实体上执行“repository.save()”之后立即调用创建统计信息和兴趣的方法的方式:

    @ApiOperation("Endpoint to register/save a new profile.")
    @PostMapping(value = "/save")
    public Profile saveProfile(@RequestBody ProfileDTO profileDTO) throws RestRequestException, CouplerPlanLimitationException {
        profileService.verifyUserCanSaveProfile(profileDTO.getUserId());
        Profile profile = profileService.save(profileFactory.newProfileDtoToProfile(profileDTO));
        profile = profileFactory.enrichProfile(profile, profileDTO);
        return profile;
    }

很抱歉发了这么长的帖子,但我不能比这个更能减少问题,而且仍然有一个可重现和易于理解的代码可以分享。

java rest spring-data-jpa many-to-many composite-primary-key
1个回答
0
投票

我用this解决了这个问题。我用一个简单的例子构建了一个 Github 存储库

我填充对象的方法保存它但具有不同的结构:

private Set<ProfileStat> buildProfileStat(Collection<Stat> stats, Profile profile) {
    Set<ProfileStat> profileStats = new HashSet<>();
    for(Stat stat : stats) {
        ProfileStatId profileStatId = new ProfileStatId(stat.getId(), profile.getId());
        ProfileStat profileStat = new ProfileStat(profileStatId, fals e);
        profileStat.setProfile(profile);
        profileStat.setStat(stat);
        profileStats.add(profileStatService.save(profileStat));
    }
    return profileStats;
}

private Set<ProfileInterest> buildProfileInterest(Collection<Interest> interests, Profile profile) {
    Set<ProfileInterest> profileInterests = new HashSet<>();
    for(Interest interest : interests) {
        ProfileInterestId profileInterestId = new ProfileInterestId(interest.getId(), profile.getId());
        ProfileInterest profileInterest = new ProfileInterest(profileInterestId, false);
        profileInterest.setProfile(profile);
        profileInterest.setInterest(interest);
        profileInterests.add(profileInterestService.save(profileInterest));
    }
    return profileInterests;
}

我必须在

ProfileStat
实体上添加一个构造函数,它接受 ID 类和额外的列但不需要对象;您稍后会添加它们。不知道能不能加一下

我还必须更改填充“配置文件”的方式,从

profile.setLanguages(buildProfileStat(findStats(profileDTO.getLanguages()), profile));
buildProfileStat(findStats(profileDTO.getLanguages()), profile);
.

我无法将保存的列表设置回它的主要对象实例,Profile;它抛出 Stackoverflow 异常。可能有一些解决方法。

© www.soinside.com 2019 - 2024. All rights reserved.