@OneToOne 映射在我的 Java Spring 项目中不起作用

@OneToOne mapping isnt working in my Java Spring project

所以我正在整理我的小 Spring 项目,我注意到出于某种原因 @OneToOne 注释没有为我完成它的工作,这反过来导致另一个模型出现问题。

github link : https://github.com/eamonmckelvey/sports-app

基本上,我有一个用户模型 class、一个团队模型 class 和一个玩家模型 class。 我希望只有一个用户能够创建一个团队,一个团队有很多玩家。 但是,我可以根据需要向我的用户添加任意​​数量的团队,这是错误的。

提供的所有答案都要求我为我的用户添加一个无参数构造函数和一个构造函数 class,但是当我这样做时,我在 class 的注册中遇到错误。

请帮忙。

1。用户模型

 @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;
       }
   }

2。团队模型

@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;

3。团队管理员

@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";
}

4。注册表

@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));
}
}

5。注册控制器

@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";
}

6。用户详细信息 class

@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");
}

1) 一个用户可以拥有一个团队。这意味着 OneToOne 用户和团队之间的关系。您不需要使用来自团队模型的 @OneToOne.Remove @OneToOne 注释来注释用户和团队。 需要的更改是:

用户模型:

@Entity
class User{ 

    @Id
    private String id;

    @OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinColumn(name = "team_id")
    private Team team;

//other fields
}

团队模型:

@Entity
class Team{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private  String teamName;
    //other field
    }

2) 一支球队有很多球员需要@OneToMany

所以,我复制了你的代码并做了一些修改。经过以下更改后,您的代码可以正常工作。

1) 从用户 class 的下方字段中删除 final 关键字(初始化它们似乎不是一个好主意)。

    private final String username;
    private final String password;

2) 用户和团队不应该有相同的序列化版本。

private static final long serialVersionUID = 1L;

3) 进行上述更正后。你的代码会给你实际的错误 "nested exception is javax.persistence.PersistenceException"

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)

..............
..........

    Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "user"

为避免它,请在您的模型中进行以下更改:

将@Table(name="users") 放入用户模型中。

型号如下:

@Entity
@Table(name="users")
public class User {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;
    private String username;
    @OneToOne(mappedBy = "user")
    private Team team;

    public User() {
    }

}

团队模型

@Table(name="teams")
public class Team {


    @Id
    private Long id;

    @OneToOne
    @MapsId
// or you can use
//    @OneToOne
//    @JoinColumn(name="user_id")
    private User user;

    private  String teamName;

    public Team() {
    }

}

按照上面的代码。这对我来说可以。测试控制器检查:

 @RequestMapping(value = "/test", method = RequestMethod.GET)
    public ResponseEntity<?> test() {
        User user = userRepository.findById(2l);
        Team team = user.getTeam();
        return new ResponseEntity(team, HttpStatus.OK);

    }
}

希望对您有所帮助。

您的代码存在几个问题:

  1. @JoinColumn child 一侧缺失。它甚至不在 parent 一边。在 User 实体中声明了 @OneToOne(cascade = CascadeType.ALL,mappedBy = "user"),但它没有映射到 child class.
  2. FetchType.LAZY 在 one-to-one 中并没有给你太多性能,因为休眠需要检查数据库是否存在 object 以了解 return 是否存在代理或 null.
  3. 您正在 TeamController 中保存一个 child 实体:service.save(team);,但是没有从 TeamUser 的级联。

尝试以下映射:

public class User implements UserDetails {

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "user")
    private Team team;

    // other fields
}

public class Team implements Serializable {

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User user;

    // other fields
}

并保持双方同步。而不是:

team.setUser(user);
service.save(team);

在您的 TeamController 中尝试以下代码(您必须自动装配 UserRepository):

team = service.save(team);
team.setUser(user);
user.setTeam(team);
userRepository.save(user);

嘿,所以我在这里找到了我的代码的修复程序。

1。团队管理员

      @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";
  }

2。团队模型

   @OneToOne(fetch = FetchType.EAGER)
   @JoinColumn(name = "user_id", referencedColumnName = "id")
   private User user;

3。用户模型

删除了此处不需要的 OneToOne

4。团队回购

@Repository
public interface TeamRepository extends JpaRepository<Team, Long> {
Team findAllById(Long id);


long countAllByUser(final User user);

}