Fetch type设置为lazy,但它仍然hibernate发送第二个请求

问题描述 投票:0回答:1

虽然 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=?
java spring spring-boot spring-data-jpa spring-data
1个回答
0
投票

问题是由

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 的一篇好文章。

© www.soinside.com 2019 - 2024. All rights reserved.