I have 2 entity. One of them User, and the other one is Followers. I'm trying to make a follower system like Twitter. User can follow another user but, i want to check if user followed, don't do it again.
This is my Follower Entity :
@Entity
public class Followers {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private long id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="from_user_fk")
@JsonIgnore
private User from;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="to_user_fk")
@JsonIgnoreProperties({ "password", "balance","id","mail" })
private User to;
public Followers() {};
public Followers(User from, User to) {
this.from = from;
this.to = to;
}
public User getFrom() {
return from;
}
public void setFrom(User from) {
this.from = from;
}
public User getTo() {
return to;
}
public void setTo(User to) {
this.to = to;
}
}
And this is the Service class :
public ResponseEntity<?> followUser(String username, User user) {
User byUsername = getByUsername(username);
List<Followers> followers1 = byUsername.getFollowers();
List<Followers> collect = followers1.stream().filter(p -> p.getTo().getId().equals(user.getId())).collect(Collectors.toList());
if(followers1.size()>0){
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("e");
}
Followers followers = new Followers();
followers.setFrom(user);
followers.setTo(byUsername);
followersRepository.save(followers);
return ResponseEntity.ok(new GenericResponse("Followed"));
}
public List<Followers> getUserFollowers(String username) {
User byUsername = getByUsername(username);
List<Followers> followers = byUsername.getFollowers();
return followers;
}
As you can see, I got the followers of the user I want to follow, and try to check if its following or not. But I couldn't.
Any help would be appreciated
CodePudding user response:
What you've built is incredibly inefficient:
- Go to the DB and fetch all followers for a given user.
- Then check through these if the person you'd like to add already exists.
- If no, add it.
- If yes, don't do anything or show an error.
The fail whale is in your near future with this kind of inefficiency.
There's a much, much simpler way. Just.. add it! Don't do any check at all.
Your DB should be configured to disallow having the same user/follower pair, so if you attempt to pull that stunt when that user already has that follower, the DB will refuse and throw an exception that indicates that there's a DB constraint violation. That's your cue to render whatever error you please.
Note that 'check if X is allowed, if yes, do X' is fundamentally broken when talking about multicore architecture. What you're forgetting: What if the user 'double clicks' the 'add follower' link? Then 2 requests start, simultaneously. They both check if X is already a follower (they are not), then they both add X as follower (and now X is a double-follower which you did not want).
Generally if a DB is involved, it is better at data consistency and transactions support, so use the best tool for the job: A DB constraint.