Set FetchType
to LAZY
.
@ManyToMany(fetch = FetchType.LAZY ,cascade = {CascadeType.ALL})
Now, even if the data exists on the database, it'll be retrieved as null. If you want them to be returned, then just invoke a getter to this property so hibernate will go and select them from your database.
This is useful to prevent infinite recursion while retrieving data from the database.
UPDATE
The recursive loop will happen because when spring serialize the object to JSON, jackson will use getters and setters to retrieve the data.
This way, hibernate will retrieve the data from the database, even if FetchType
is equals LAZY
.
One workaround is to have a DTO class containing exactly what you want to return.
For example:
User.java
public class User {
private Long id;
private String name;
private Date birthDate;
private List<Post> posts;
public User() {}
public User(Long id, String name, Date birthDate) {
this.id = id;
this.name = name;
this.birthDate = birthDate;
this.posts = new ArrayList < >();
}
// getters and setters..
}
Post.java
public class Post {
private Long id;
private String title;
private String content;
private User owner;
public Post() {}
public Post(Long id, String title, String content, User owner) {
this.id = id;
this.title = title;
this.content = content;
this.owner = owner;
}
// getters and setters..
}
UserDTO.java
public class UserDTO {
private Long id;
private String name;
private Date birthDate;
public UserDTO(User user) {
this.id = user.getId();
this.name = user.getName();
this.birthDate = user.getBirthDate();
}
// getters and setters..
}
PostDTO.java
public class PostDTO {
private Long id;
private String title;
private String content;
public PostDTO(Post post) {
this.id = post.getId();
this.title = post.getTitle();
this.content = post.getContent();
}
// getters and setters..
}
UserService.java
@Service
public class UserService {
@Autowired
UserRepository userRepository;
public List<UserDTO> retrieveAll() {
List <UserDTO> users = userRepository.findAll().stream().map(user -> new UserDTO(user)).collect(Collectors.toList());
return users;
}
}
This will not enter in infinite recursion, because the User posts will not be rendered.
Now, if you don't want to return List
of UserDTO
(List<UserDTO>
), you can create a helper class which returns a user based on the UserDTO
informations.
Something like that:
Helper.java
public class Helper {
public static User userFromDTO(UserDTO userDTO) {
return new User(userDTO.getId(), userDTO.getName(), userDTO.getBirthDate());
}
}
Now in your service:
@Service
public class UserService {
@Autowired
UserRepository userRepository;
public List<User> retrieveAll() {
List<User> users = userRepository.findAll();
users = users.stream().map(user -> userFromDTO(new UserDTO(user))).collect(Collectors.toList());
return users;
}
}