Spring Data JPA ManyToOne 和 OneToMany – 无法找到 ID 为… 的实体

huangapple go评论72阅读模式
英文:

Spring Data JPA ManyToOne and OneToMany - Unable to find entity with ID

问题

我有三个表 - role(角色),user(用户)和user_role(用户角色)。这应该是一个ManyToMany(多对多)关系,但由于我还想为user_role生成id,所以我使用了OneToMany(一对多)和ManyToOne(多对一)。

以下是只包含相关字段的实体示例:

@Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "role")
    private Set<UserRole> userRoles;
}

@Entity
public class User {
    @Id
    private String id;
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
    private Set<UserRole> userRoles;
}

@Entity
public class UserRole {
    @Id
    private String id;
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
    @ManyToOne
    @JoinColumn(name = "role_id")
    private Role role;
}

然后,这是我如何创建它们的实例并保存到数据库的方法:

// 从数据库中通过ID检索
Role role = ...;

// 使用UUID生成ID字符串
User user = new User();
user.setId("abc");

// 使用UUID生成ID字符串
UserRole userRole = new UserRole();
userRole.setId("xyz");

Set<UserRole> userRoles = Set.of(userRole);

role.setUserRoles(userRoles);
user.setUserRoles(userRoles);

userRole.setUser(user);
userRole.setRole(role);

userRepository.save(user);

无论我如何尝试和搜索,我都无法解决的问题:

2020-09-27 23:41:58.917  WARN 21948 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.orm.jpa.JpaObjectRetrievalFailureException: 无法找到ID为xyz的com.example.entity.UserRole;嵌套异常是javax.persistence.EntityNotFoundException: 无法找到ID为xyz的com.example.entity.UserRole]

请帮我解决这个问题。谢谢。

英文:

I have three tables - role, user, and user_role. This is supposed to be ManyToMany but since I also want to generate id for the user_role, I used OneToMany and ManyToOne.

Here are my entities with relevant fields only:

@Entity
public class Role {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Integer id;
    @OneToMany(fetch = FetchType.EAGER, mappedBy = &quot;role&quot;)
    private Set&lt;UserRole&gt; userRoles;
}

@Entity
public class User {
	@Id
	private String id;
	@OneToMany(fetch = FetchType.EAGER, mappedBy = &quot;user&quot;)
	private Set&lt;UserRole&gt; userRoles;
}

@Entity
public class UserRole {
    @Id
    private String id;
    @ManyToOne
    @JoinColumn(name = &quot;user_id&quot;)
    private User user;
    @ManyToOne
    @JoinColumn(name = &quot;role_id&quot;)
    private Role role;	
}

Then, this is how I create instances of them and save to the DB:

// Retrieve from DB by ID
Role role = ...;

// ID String is generated from UUID
User user = new User();
user.id(&quot;abc&quot;);

// ID String is generated from UUID
UserRole userRole = new UserRole();
userRole.setId(&quot;xyz&quot;);

Set&lt;UserRole&gt; userRoles = Set.of(userRole);

role.setUserRoles(userRoles);
user.setUserRoles(userRoles);

userRole.setUser(user);
userRole.setRole(role);

userRepository.save(user);

The issue that I find it difficult to resolve no matter how I have tried and googled:

2020-09-27 23:41:58.917  WARN 21948 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find com.example.entity.UserRole with id xyz; nested exception is javax.persistence.EntityNotFoundException: Unable to find com.example.entity.UserRole with id xyz]

Please help me. Thanks.

答案1

得分: 3

Stern说得很对。你正试图仅保存user实体,但是你没有在任何地方设置级联。因此,当你调用userRepository.save(user)时,显然缺少角色实体。要么在保存user之前保存依赖实体,要么更好的做法是在你的User类中的userRoles字段上面添加级联。

英文:

Stern has good point. You are trying to save only user entity, but you don't have any cascade set anywhere. So when you call userRepository.save(user) it is obviously missing role entities. Either save dependent entities before saving user, or better, add cascade above userRoles field in your User class etc.

答案2

得分: 3

如在其他地方提到的,你需要设置最小值:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "user" , cascade = CascadeType.ALL)
private Set<UserRole> userRoles;

或者最小化:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "user" , cascade = 
        CascadeType.PERSIST)
private Set<UserRole> userRoles;

但是如果你需要按User获取UserRoles,你需要设置:

// 对于列表中的每个UserRole。
userRole.setUser(user);

在持久化之前,否则列表将不会被填充。

英文:

As mentioned elsewhere you need to se minimum:

@OneToMany(fetch = FetchType.EAGER, mappedBy = &quot;user&quot; , cascade = CascadeType.ALL)
private Set&lt;UserRole&gt; userRoles;

or minimum:

@OneToMany(fetch = FetchType.EAGER, mappedBy = &quot;user&quot; , cascade = 
        CascadeType.PERSIST)
private Set&lt;UserRole&gt; userRoles;

But also if you need to fetch UserRoles by User you need to set:

// for each UserRole in the list.
userRole.setUser(user);

before persisting otherwise list will not be populated.

huangapple
  • 本文由 发表于 2020年9月28日 00:28:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/64090756.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定