虽然 fetch 类型是惰性的,但出于某种原因,hibernate 会发送第二个请求并获取惰性请求。 由于某种我不明白的原因,我已经处理这个问题几天了。我在互联网上尝试了一些方法,但不幸的是我无法修复它,如果您能通过查看我的代码来帮助我,我将非常感激。
用户实体
@Entity
@Table(name = "users")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(name = "username", length = 50)
private String username;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_friends" , joinColumns = @JoinColumn(name = "user_id") , inverseJoinColumns = @JoinColumn(name = "friend_id"))
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<User> friends = new HashSet<>();
}
用户服务
@Service
@Transactional
public class UserService implements ICrudService<User> {
@Autowired
private UserRepository repository;
@Override
@Transactional
public List<User> findAll() {
return repository.findAll();
}
@Override
@Transactional
public User findById(Long id) throws Exception {
return repository.findById(id).orElseThrow(() -> new Exception("Kullanici Bulunamadi"));
}
@Override
@Transactional
public User create(User user) {
return repository.save(user);
}
@Override
public void delete(Long id) {
repository.deleteById(id);
}
}
用户控制器
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/all")
public List<User> getUsers(){
return userService.findAll();
}
@GetMapping("/{userId}")
public User getUserById(@PathVariable Long userId) throws Exception {
return userService.findById(userId);
}
@PostMapping
public User saveUser(@RequestBody User user){
return userService.create(user);
}
@DeleteMapping("/{userId}")
public void deleteUserById(@PathVariable Long userId){
userService.delete(userId);
}
}
我使用 JpaReository 作为服务中的存储库
“/users/all”的输出如下所示
输出
[
{
"id": 1,
"username": "testUser",
"email": "[email protected]",
"password": "verystrongpasword",
"friends": []
}
]
这是hibernate sql格式
Hibernate:
select
u1_0.id,
u1_0.email,
u1_0.password,
u1_0.username
from
users u1_0
Hibernate:
select
f1_0.user_id,
f1_1.id,
f1_1.email,
f1_1.password,
f1_1.username
from
user_friends f1_0
join
users f1_1
on f1_1.id=f1_0.friend_id
where
f1_0.user_id=?
问题是由
Lombok
@Data
注释触发的,因为它在底层使用 @ToString
,默认情况下使用 class
的所有字段来创建它。
有 2 种可能的解决方案:
1.创建您自己的
toString()
方法,Lombok
然后将退避生成 toString。
2.添加
@ToString
注释并使用@ToString.Exclude
排除所有惰性和双向字段。
在你的情况下,类似下一个:
@Entity
@Table(name = "users")
@Data
@ToString
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(name = "username", length = 50)
private String username;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_friends" , joinColumns = @JoinColumn(name = "user_id") , inverseJoinColumns = @JoinColumn(name = "friend_id"))
@OnDelete(action = OnDeleteAction.CASCADE)
@ToString.Exclude
private Set<User> friends = new HashSet<>();
}
有关它和其他案例的更多详细信息,您可以找到 Lombok-Data-Ojects-Arent-Entities Marten Deinum 的一篇好文章。