如何在 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,因此如果您想要获取它们,您需要一个事务将它们从分离的关系加载到托管状态,然后能够将其附加到您要保存的对象
我想用特定元素保存两个或更多人彼此的关系。具有技能和特定地址的人应该相互联系。通常我创建一个 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,因此如果您想要获取它们,您需要一个事务将它们从分离的关系加载到托管状态,然后能够将其附加到您要保存的对象