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
Advertisement
Answer
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.