我有一个多对一的关系,我想可以为空。 这是父母:
@Entity
@Table(name = "C_CUSTOMER")
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@OneToMany (fetch = FetchType.LAZY, mappedBy="user", cascade = CascadeType.REMOVE)
private List<Profile> profiles;
}
还有孩子:
@Entity
@Table(name = "C_PROFILE")
class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(optional = true)
@JoinColumn(nullable = true, name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
private User user;
}
当我尝试保存没有userId的配置文件时,会引发以下错误:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : fr.entity.Profile.user -> fr.entity.User
如果字段userId有一个值,那么它将顺利进行。
我尝试了其他有关SO的问题的答案,但到目前为止没有任何效果。最简单的方法是放弃实体文件中的关系并使用Integer customerId
,但这对我来说并不十分令人满意,因为这意味着级联删除将不再起作用。
先谢谢了。
问题来自实体<-> dto映射。我添加了有关此问题的答案,如果遇到解决方法,可能会进行编辑。
答案 0 :(得分:0)
在我的计算机上尝试过您的代码。以下是我的实体类:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Table(name = "C_PROFILE")
@Data
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@ManyToOne(optional = true)
@JoinColumn(nullable = true, name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
private User user;
}
用户类别:
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Table(name = "C_CUSTOMER")
@Data
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String email;
@OneToMany (fetch = FetchType.LAZY, mappedBy="user", cascade = CascadeType.REMOVE)
private List<Profile> profiles;
}
存储库:
import org.springframework.data.jpa.repository.JpaRepository;
import io.polarisdev.returns.model.Profile;
public interface ProfileRepository extends JpaRepository<Profile, String> {
}
无需用户即可保存配置文件的代码:
Profile p = new Profile();
p.setName("Name");
profileRepository.save(p);
答案 1 :(得分:0)
因此,在深入研究生成的文件之后:目前尚无解决方案。问题出在实体<-> dto之间,使用mapstruct进行了映射:没有提到这一步,难怪它对我来说不起作用……嗯,配置文件映射器包含以下内容:
protected User profileToUser(Profile profile) {
if ( profile == null ) {
return null;
}
User user = new User();
User.setId(profile.getUserId());
return user;
}
意思是我需要在保存Profile
之前重新分配一个空值。显然在github上有关于此的票证,所以请拭目以待。似乎也有一些建议可以使其正常工作,因此,如果我遇到一个可行的建议,我将编辑此答案(除非之前有人提出解决方案)。
在对mapstruct git和SO进行了一些研究之后,我遇到了一个可行的解决方案,尽管它并不十分优雅。
@AfterMapping
public Profile doAfterMapping(@MappingTarget Profile entity) {
if (entity != null && entity.getUser().getId() == null) {
entity.setUser(null);
}
return entity;
}
所以...我将问题重复一遍。多亏了那些对我有帮助的人(尽管如果我更加警惕的话,我就不必发帖了)。