java - M:N 表不更新
问题描述
我在用户和文档之间有 m:n 关系。我正在创建 Document 对象,获取 List - setDocumentsForUsers() 然后我正在持久化该对象。问题是,该文档是在我的数据库中创建的,但不是 M:N 关系。我究竟做错了什么?我在坚持后尝试调用flush,但它根本没有帮助。
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "first_name")
private String firstName;
private String surname;
private String email;
private String password;
@ManyToMany
@JoinTable(
name = "users_roles",
joinColumns = @JoinColumn(
name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(
name = "role_id", referencedColumnName = "id"))
private List<Role> roles;
@JsonIgnore
@ManyToMany
@JoinTable(
name="users_documents",
joinColumns = @JoinColumn(
name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(
name="document_id", referencedColumnName = "id"))
private List<Document> usersDocuments;
@OneToMany(mappedBy="user")
private List<Document> sharedDocuments;
public User() {
}
public User(String firstName, String surname, String email, String password) {
this.firstName = firstName;
this.surname = surname;
this.email = email;
this.password = password;
}
public void setId(long id) {
this.id = id;
}
public long getId() {
return id;
}
public String getEmail() {
return email;
}
public void setEmail(String email){this.email = email;}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public List<Role> getRoles() {
return roles;
}
public List<Document> getUsersDocuments() {
return usersDocuments;
}
public void setUsersDocuments(List<Document> usersDocuments) {
this.usersDocuments = usersDocuments;
}
public List<Document> getSharedDocuments() {
return sharedDocuments;
}
public void setSharedDocuments(List<Document> sharedDocuments) {
this.sharedDocuments = sharedDocuments;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return getId() == user.getId();
}
@Override
public int hashCode() {
return Objects.hash(getId());
}
@Override
public String toString() {
return "User{" +
"firstName='" + firstName + '\'' +
", surname='" + surname + '\'' +
", email='" + email + '\'' +
", roles=" + roles +
'}';
}
}
我的文档类:
@Entity
public class Document {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(unique = true)
private String name;
private String title;
private String description;
@Column(name = "resource_path")
private String resourcePath;
@Column(name = "upload_datetime", columnDefinition = "DATETIME")
@Temporal(TemporalType.TIMESTAMP)
private Date uploadDatetime;
@ManyToMany(mappedBy = "usersDocuments")
private List<User> documentsForUsers;
@ManyToOne
@JoinColumn(name="user_id", nullable=false)
private User user;
public Document() {
}
public Document(String title, String description){
this.title = title;
this.description = description;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getResourcePath() {
return resourcePath;
}
public void setResourcePath(String resourcePath) {
this.resourcePath = resourcePath;
}
@Override
public String toString() {
return "Document{" +
"id=" + id +
", title='" + title + '\'' +
", description='" + description + '\'' +
", resourcePath='" + resourcePath + '\'' +
", uploadDatetime=" + uploadDatetime + '\'' +
". user=" + user;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Document)) return false;
Document document = (Document) o;
return getId() == document.getId();
}
@Override
public int hashCode() {
return Objects.hash(getId());
}
public Date getUploadDatetime() {
return uploadDatetime;
}
public void setUploadDatetime(Date uploadDatetime) {
// Date startDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(uploadDatetime.toString());
this.uploadDatetime = uploadDatetime;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<User> getDocumentsForUsers() {
return documentsForUsers;
}
public void setDocumentsForUsers(List<User> documentsForUsers) {
this.documentsForUsers = documentsForUsers;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
执行此操作:
Optional<User> user = userService.getUserByEmail(createdBy);
Document document = new Document(title, desc);
document.setUploadDatetime(new Date());
document.setUser(user.get());
List<User> users = userService.getUsersByRoles(roles);
document.setDocumentsForUsers(users);
saveDocument(document);
@Override
public void saveDocument(Document document) {
entityManager.persist(document);
}
解决方案
您的班级用户是关系@ManyToMany的所有者
List<Document> usersDocuments;
因为用户有@JoinTable。文档类是一个Inverse end。如果一个文档被持久化,那么一个数据将被保存而没有关系。因为 Inverse end 只关心自己,不关心关系。
默认情况下,您只能从所有者方保留关系。
在我测试的情况下,为了能够从相反的一端保持关系,那么在你的情况下:
- 在文档中添加级联:
@ManyToMany(cascade = CascadeType.PERSIST, mappedBy = "usersDocuments") private List<User> documentsForUsers;
并在您的设置器中添加一个新代码:
public void setDocumentsForUsers(List<User> documentsForUsers) {
if (documentsForUsers != null){
documentsForUsers.forEach(u -> {
u.getUsersDocuments().add(this); //here you should have not-null list u.getUsersDocuments()
});
}
this.documentsForUsers = documentsForUsers;
}
- 在用户类中添加级联:
@ManyToMany(cascade = CascadeType.PERSIST)
和
private List<Document> usersDocuments = new ArrayList<>();
推荐阅读
- hadoop - Hive 更新期间 HDFS 中发生了什么(真正)?
- java - 如何在 JBoss 中部署没有活动 JMS 配置的 MDB?
- c# - x64 C# 应用程序中结构中的 FieldsOffset
- java - FXMLLoader.load() 在 pre-java 9 样式中工作正常,但在模块中失败
- html - 当导航栏在移动设备上折叠时,背景正文向上滚动
- typescript - 有没有办法获取打字稿对象的所有必需属性
- sql - SQL 在 WHERE 语句中使用参数
- c# - 为什么我调用 ASPNET Core 2.1 Database Migrate 的实现没有实际应用迁移?
- java - 使用 Java 流按集合属性分组
- c# - 在 TCP 中按下 Enter 键之前如何接收数据流?