Java 如何正确地将记录添加到jpa onetomany联接表
我正在开发一个文件系统,其中有3张表格。PROJECTS表包括projectid、项目名称和其他详细信息,请参见下文。这是一个现有的类和填充的模式,如果可能的话,我不想修改应用程序的这一部分 名为ProjectClassification的文件夹表由folderid和foldername组成,是单向onetomany关系的拥有方 Project\u文件夹是一个联接表。我使用JPA2.0EclipseLink和JSF2.0作为我的web框架 我的基本问题是无法使用合并操作将重复记录添加到联接表中。MERGE适用于添加记录,直到拥有的键已经存在,之后它将只更新联接表。我知道这是它应该工作的方式,但我需要添加新记录,即使有拥有密钥的副本。这将允许我在同一文件夹中存储不同的项目 我在这里已经浏览了一些其他问题,例如: 这说明了在联接表中将一个实体添加到另一个实体需要什么,但我需要更多地了解如何正确地将添加的实体持久化或合并到数据库中 文件夹实体类:Java 如何正确地将记录添加到jpa onetomany联接表,java,mysql,hibernate,jpa,jpa-2.0,Java,Mysql,Hibernate,Jpa,Jpa 2.0,我正在开发一个文件系统,其中有3张表格。PROJECTS表包括projectid、项目名称和其他详细信息,请参见下文。这是一个现有的类和填充的模式,如果可能的话,我不想修改应用程序的这一部分 名为ProjectClassification的文件夹表由folderid和foldername组成,是单向onetomany关系的拥有方 Project\u文件夹是一个联接表。我使用JPA2.0EclipseLink和JSF2.0作为我的web框架 我的基本问题是无法使用合并操作将重复记录添加到联接表中。
@Entity
@Table(name = "PROJECTCLASSIFICATIONS")
public class ProjectClassifications implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int proclassid;
private int projectid;
private String classification;
@OneToMany(cascade = CascadeType.ALL)
@JoinTable(name = "PROJECT_CLASSF_JOIN",
joinColumns = @JoinColumn(name = "proclassid", referencedColumnName = "proclassid"),
inverseJoinColumns = @JoinColumn(name = "projectid", referencedColumnName = "projectid", unique = true))
private Collection<Projects> projects;
public ProjectClassifications() {
}
public ProjectClassifications(String classification) {
this.classification = classification;
}
public ProjectClassifications(int proclassid, int projectid) {
this.proclassid = proclassid;
projects = new ArrayList<Projects>();
}
public ProjectClassifications(Projects newProject) {
projects = new ArrayList<Projects>();
}
public void addProject(Projects newProject) {
if(!getProjects().contains(newProject))
getProjects().add(newProject);
}
....
....
然后,我使用两个html选择列表来选择projectid和proclassid的值,它们使用JSF托管bean调用以下Methodoid:
public String makeProClassRecord() {
newProClass = new ProjectClassifications(proclassid, projectid);
newProject = proServ.findByProjectId(projectid);
newProClass.addProject(newProject);
facade.update(newProClass);
//facade.save(newProClass);
return showProclass();
}
我的问题是:
1“合并”操作是否用于将记录添加到联接表中
2是否有方法添加包含重复键的记录外键使用合并在联接表中表示为新记录
3应该用坚持来实现问题2吗
4为联接表本身创建一个实体并简单地使用PERSIST方法插入记录是否更好
非常感谢,所以几周前我自己解决了这个问题,并想分享答案。我没有对任何目标实体执行合并或持久化操作,而是创建了一个连接表和从项目实体到下面的ProjectFileSystem连接表实体的单向OneToMany关系,并简单地使用该实体执行持久化操作。我需要为不同的项目添加重复的文件夹,或者在单个文件夹项下存储多个项目,这样在实际的联接表实体中执行CRUD操作似乎比从目标实体执行CRUD操作更有效。希望这有助于:
@Entity
@Table(name = "PROFOLDERSYS_JOIN")
public class ProjectFileSystem implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int foldersysid;
private int proclassid;
private int projectid;
private String projectName;
private String folderName;
public ProjectFileSystem() {
}
public ProjectFileSystem(int proclassid, int projectid,
String projectName, String folderName) {
this.proclassid = proclassid;
this.projectid = projectid;
this.projectName = projectName;
this.folderName = folderName;
}
// getters and setters
}
bean中的方法是:
public String makeProSys() {
newProSys = new ProjectFileSystem(proclassid, projectid, classification, projectName);
newProject = proServ.findByProjectId(projectid);
projectName = newProject.getProjectName();
newProSys.setProjectName(projectName);
newProClass = facade.findByContactId(proclassid);
classification = newProClass.getClassification();
newProSys.setFolderName(classification);
profilFacade.save(newProSys);
return showProSys();
}
为什么有一个类型为Set的字段标记为OneToOne?!您不会将对象添加到联接表。。。您只需在双向时在两侧设置关系,然后根据对象的状态进行持久化/合并。OnetoOne字段是一个先前的错误,在我开始处理它之前,它出现在程序上。我删除了这个,它不会以任何方式影响我的问题。通常我不会使用联接表,但在这种情况下,我可能需要一个联接表?正如我在问题中提到的,我不想干扰Projects实体的现有CRUD操作。我只是想创建一个归档系统,其他一切都完好无损。因此,这不意味着我需要一个单向的onetomany关系,而连接表是实现这一点的正确方法吗?调用persist还是merge取决于对象处于什么状态。它是持久的吗?独立的暂时的,即还没有持续?这是非常有用的了解。我在Projects实体中已经有了一个transient字段。我认为我的选项仅限于分离状态,这就是为什么我必须对联接表案例使用merge。Persist为Projects和ProjectClassifications实体创建新对象,而不是我想要的连接表。也不会因为重复的键条目而导致IntegrityViolationConstraint?所以我不是被迫使用合并吗?
public String makeProSys() {
newProSys = new ProjectFileSystem(proclassid, projectid, classification, projectName);
newProject = proServ.findByProjectId(projectid);
projectName = newProject.getProjectName();
newProSys.setProjectName(projectName);
newProClass = facade.findByContactId(proclassid);
classification = newProClass.getClassification();
newProSys.setFolderName(classification);
profilFacade.save(newProSys);
return showProSys();
}