So I am tidying up my small Spring project and I noticed for some reason the @OneToOne annotation is not doing its job for me which in turn causes issues in another model.
github link : https://github.com/eamonmckelvey/sports-app
Basically, I have a User model class, a team model class and a player model class. I want only one user to be able to create one team, and one team to have many players. However, I am able to add as many teams to my user as I want which is wrong.
All the answers provided require me to add a no arg constructor and a constructor for my users class, but when I do this I get an error in my registration from class.
Please help.
@Entity
@Data
@NoArgsConstructor(access= AccessLevel.PRIVATE, force=true)
@RequiredArgsConstructor
public class User implements UserDetails {
@OneToOne(cascade = CascadeType.ALL,mappedBy = "user")
private Team team;
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
private final String username;
private final String password;
//private final String fullname;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
@Data
@Entity
@Table(name="User_Team")
public class Team implements Serializable {
@OneToOne(fetch= FetchType.LAZY)
private User user;
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
//@NotBlank(message="Team Name is required")
private String teamName;
//@NotBlank(message="Location is required")
private String location;
//@NotBlank(message="Nickname required")
private String nickName;
private String yearEstablished;
public Sport sport;
private Divison divison;
@Slf4j
@Controller
@SessionAttributes("Team")
public class TeamController {
private TeamRepository teamRepository;
public TeamController(TeamRepository teamRepository) {
this.teamRepository = teamRepository;
}
@Autowired
TeamRepository service;
@GetMapping("/team")
public String displayTeam(Model model) {
model.addAttribute("team", service.findAll());
return "/team";
}
@GetMapping("/addTeam")
public String showSignUpForm(User user) {
return "addTeam";
}
@PostMapping("/addTeam")
public String processOrder(@Valid Team team, BindingResult result, SessionStatus
sessionStatus,
@AuthenticationPrincipal User user, Model model) {
if (result.hasErrors()) {
return "addTeam";
}
team.setUser(user);
service.save(team);
model.addAttribute("team", service.findAll());
return "team";
}
@Data
public class RegistrationForm {
private String username;
private String password;
//private String fullname;
public User toUser(PasswordEncoder passwordEncoder) {
return new User(
username, passwordEncoder.encode(password));
}
}
@Controller
@RequestMapping("/register")
public class RegistrationController {
private UserRepository userRepo;
private PasswordEncoder passwordEncoder;
public RegistrationController( UserRepository userRepo,
PasswordEncoder passwordEncoder){
this.userRepo = userRepo;
this.passwordEncoder = passwordEncoder;
}
@GetMapping
public String registerForm(){
return "registration";
}
@PostMapping
public String processRegistration(RegistrationForm form){
userRepo.save(form.toUser(passwordEncoder));
return "redirect:/login";
}
@Service
public class UserRepositoryUserDetailsService implements
UserDetailsService {
private UserRepository userRepo;
@Autowired
public UserRepositoryUserDetailsService(UserRepository userRepo) {
this.userRepo = userRepo;
}
@Override
public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException {
User user = userRepo.findByUsername(username);
if (user != null) {
return user;
}
throw new UsernameNotFoundException(
"User '" + username + "' not found");
}
Hey so i found a fix here for my code.
@GetMapping("/addTeam")
public String showSignUpForm(SessionStatus sessionStatus,
@AuthenticationPrincipal User user, Model model)
{
//if the user has already the team we should not let them add another
// one
//this is due to having one to one relationship
long userHasTeamCount = service.countAllByUser(user);
if (userHasTeamCount > 0) {
return "redirect:team";
}
return "addTeam";
}
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
Removed the OneToOne here as its not needed
@Repository
public interface TeamRepository extends JpaRepository<Team, Long> {
Team findAllById(Long id);
long countAllByUser(final User user);
}