Adr*_*zyk 3 java spring hibernate spring-boot
我认为我正在推动 Spring Boot 和 Hibernate 使用的极其简单的情况。我的目的是将有关班级的信息存储在班级Cyclist内部的关系User中OneToOne。
在注册期间,User创建类的实例并将其存储到数据库中。当用户刷新/home页面时,点击计数器会增加并保存(更新)实体。这是一个简单的会话测试和更新数据库,其工作原理如下:
@Controller
@SessionAttributes("user")
@RequestMapping("/home")
public class HomeController {
@Autowired private UserSession userSession;
@Autowired private UserDAO userDAO;
@GetMapping
public String home(Model model) {
User user = userSession.getUser();
user.setClicks(user.getClicks() + 1);
userDAO.save(user);
return "home";
}
}
Run Code Online (Sandbox Code Playgroud)
当用户填写表单时就会出现问题/createCyclist:
@Autowired private UserDAO userDAO;
@PostMapping
public String createCyclist(@Valid CyclistCreationForm cyclistCreationForm, BindingResult bindingResult, Model model) {
/* Form handling */
User user = userSession.getUser();
Cyclist cyclist = new Cyclist(user, cyclistCreationForm.getHeight(), cyclistCreationForm.getGender());
user.setCyclist(cyclist);
userDAO.save(user);
return "redirect:/home";
}
Run Code Online (Sandbox Code Playgroud)
上面的执行没有异常,但强制用户浏览器加载 /home 页面。从这一刻起,调用userDAO.save(user)会/home产生异常:
javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session [<package>.Cyclist#1]
Run Code Online (Sandbox Code Playgroud)
其余的异常是无用的堆栈跟踪。
这就是我设计Cyclist课程的方式:
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name="cyclists")
public class Cyclist {
private int id;
private User user;
/* Some float fields */
@Id
public int getId() {
return id;
}
@MapsId
@OneToOne
@PrimaryKeyJoinColumn
public User getUser() {
return user;
}
}
Run Code Online (Sandbox Code Playgroud)
和User班级:
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name="users")
public class User implements Serializable {
private Integer uid;
private String name;
private String password;
private Cyclist cyclist;
private int clicks;
@Id
@GeneratedValue
@NotNull
@Column(unique = true)
public Integer getUid() {
return uid;
}
@NotNull
public String getName() {
return name;
}
@NotNull
public String getPassword() {
return password;
}
@OneToOne(cascade = CascadeType.ALL)
public Cyclist getCyclist() {
return cyclist;
}
public int getClicks() {
return clicks;
}
}
Run Code Online (Sandbox Code Playgroud)
我读了 SO/google 上发布的许多问题,但不适合我的问题。
User 和 Cyclist DAO 是CrudRepository实现。我正在使用 lombok 生成样板代码。@Data我对lombok 的hashCode和生成有点了解,toString所以我尝试仅使用@Getter和@Setter。它没有解决问题。
该问题是由 引起的@MapsId。简单的@OneToOne映射只需要:
用户.java:
@OneToOne(cascade = CascadeType.ALL)
public Cyclist getCyclist() {
return cyclist;
}
Run Code Online (Sandbox Code Playgroud)
骑自行车者.java:
@OneToOne
@PrimaryKeyJoinColumn
public User getUser() {
return user;
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以通过调用setCyclistuser 和来保留所有内容userDao.save(user)。
过去我想让 Cyclist 的主键也成为等于用户 uid 的外键。这不需要users表中的附加字段。所以我尝试使用 @MapsId 并忘记它。我将尝试以本教程描述的方式实现双向共享主键:
编辑:我按照我说的做了。与骑行者的主键与用户的 id 相同的一对一映射:
用户.java:
@OneToOne(mappedBy="user", cascade = CascadeType.ALL)
public Cyclist getCyclist() {
return cyclist;
}
Run Code Online (Sandbox Code Playgroud)
骑自行车者.java:
@Id
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign",parameters=@Parameter(name="property", value="user"))
public int getId() {
return id;
}
@OneToOne
@PrimaryKeyJoinColumn
public User getUser() {
return user;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2001 次 |
| 最近记录: |