如何在 java spring boot (jpa-hibernate) 中保存(分离的)对象的关系

How to save relationship of (detached) objects in java spring boot (jpa-hibernate)

我想用特定元素保存两个或更多人彼此的关系。具有技能和特定地址的人应该相互联系。通常我创建一个 table 来保存每个元素的 ID,并在 table 中创建一行(在正常的 MySQL 和 PHP 中)。
如何在 Java Spring Boot (JPA-Hibernate-MySQL) 中解决这个问题?

当我从每个元素的存储库中创建(或更好地请求)一个“对象”(分离)并想将其保存在一个新的“存储库”(数据库)中时,我遇到了一个错误。

PartnerConnectionServiceImplementation (.java)

@Service
public class PartnerConnectionServiceImpl implements PartnerConnectionService {

    @Autowired
    private PartnerConnectionRepository partnerConnectionRepository;

    @Autowired
    private DanceSkillServiceImpl danceSkillDatabaseService;

    @Autowired
    private AddressLocationServiceImpl addressLocationDatabaseService;

    @Autowired
    private UserProfileServiceImpl userProfileDatabaseService;

@Override
    public Optional<PartnerConnection> connectPartnersWithDanceSkillAndAddressLocation(long userIdPartner1, long danceSkillIdPartner1, long addressLocationIdPartner1, long userIdPartner2, long danceSkillIdPartner2, long addressLocationIdPartner2) {

        Optional<UserProfile> userProfile1 = this.userProfileDatabaseService.getUserById(userIdPartner1);
        Optional<UserProfile> userProfile2 = this.userProfileDatabaseService.getUserById(userIdPartner2);

        Optional<DanceSkill> danceSkill1 = this.danceSkillDatabaseService.getDanceSkillById(danceSkillIdPartner1);
        Optional<DanceSkill> danceSkill2 = this.danceSkillDatabaseService.getDanceSkillById(danceSkillIdPartner2);

        Optional<AddressLocation> addressLocation1 = this.addressLocationDatabaseService.getAddressLocationById(addressLocationIdPartner1);
        Optional<AddressLocation> addressLocation2 = this.addressLocationDatabaseService.getAddressLocationById(addressLocationIdPartner2);

        if (
        (userProfile1.isPresent()) && (userProfile2.isPresent())
        ){
            Optional<PartnerConnection> theConnection = getPartnerConnectionOfPartners(
                    userProfile1.get(),
                    userProfile2.get());

            if (theConnection.isPresent()) {
                return theConnection;
            }
        }


        if (
                (userProfile1.isPresent()) && (userProfile2.isPresent()) &&
                (danceSkill1.isPresent()) && (danceSkill2.isPresent()) &&
                (addressLocation1.isPresent()) && (addressLocation2.isPresent())
        ) {
            PartnerConnection newPartnerConnection = new PartnerConnection(
                null,
                userProfile1.get(),
                danceSkill1.get(),
                addressLocation1.get(),
                userProfile2.get(),
                danceSkill2.get(),
                addressLocation2.get()
        );

        this.partnerConnectionRepository.save(newPartnerConnection);


        return Optional.of(newPartnerConnection);
        }

        return Optional.empty();
    }
...

PartnerConnection (.java)


// indicates the connecitons between partners/ users
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@Table(name = "partner_connection")
public class PartnerConnection {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;


    @OneToOne(
            fetch = FetchType.LAZY,
            cascade = CascadeType.ALL
    )
    @JoinColumn(
            name = "firstmessage_fk",    // foreign key
            nullable = true
    )
    private UserMessage firstMessage;

    @ManyToOne(
            fetch = FetchType.LAZY,
            cascade = CascadeType.ALL
    )
    @JoinColumn(name = "onepartner_fk",     // foreign key
            nullable = false)
    private UserProfile firstPartner;

    @OneToOne(
            fetch = FetchType.LAZY,
            cascade = CascadeType.ALL
    )
    @JoinColumn(
            name = "firstpartnerdanceskill_fk",    // foreign key
            nullable = false
    )
    private DanceSkill firstPartnerDanceSkill;

    @OneToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    @JoinColumn(name = "firstpartneraddresslocation_fk",    // foreign key
            nullable = false)
    private AddressLocation firstPartnerAddressLocation;

    @ManyToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    @JoinColumn(name = "secondpartner_fk",   // foreign key
            nullable = false)
    private UserProfile secondPartner;

    @OneToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    @JoinColumn(name = "secondpartnerdanceskill_fk",    // foreign key
            nullable = false)
    private DanceSkill secondPartnerDanceSkill;

    @OneToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    @JoinColumn(name = "secondpartneraddresslocation_fk",    // foreign key
            nullable = false)
    private AddressLocation secondPartnerAddressLocation;


    public PartnerConnection(UserMessage firstMessage, UserProfile firstPartner, DanceSkill firstPartnerDanceSkill, AddressLocation firstPartnerAddressLocation, UserProfile secondPartner, DanceSkill secondPartnerDanceSkill, AddressLocation secondPartnerAddressLocation) {
        this.firstMessage = firstMessage;
        this.firstPartner = firstPartner;
        this.firstPartnerDanceSkill = firstPartnerDanceSkill;
        this.firstPartnerAddressLocation = firstPartnerAddressLocation;
        this.secondPartner = secondPartner;
        this.secondPartnerDanceSkill = secondPartnerDanceSkill;
        this.secondPartnerAddressLocation = secondPartnerAddressLocation;
    }
}

错误 org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: ... nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: ... 出现在 this.partnerConnectionRepository.save(newPartnerConnection);

大家有什么通俗易懂的建议吗?

我认为你的方法应该包含@Transactional 注释。您已将所有关系标记为 LAZY,因此如果您想要获取它们,您需要一个事务将它们从分离的关系加载到托管状态,然后能够将其附加到您要保存的对象