我正在开发一个文件系统,我有3个表。项目表由项目id、项目名称和其他详细信息组成(见下文)。这是一个现有的类和填充的模式,如果可能的话,我不想修改应用程序的这一部分。
Folders表(称为ProjectClassification)由folderid和foldername组成,是单向一对一关系的拥有方。
Project_Folders是一个联接表。我正在使用JPA 2.0(EclipseLink)和JSF 2.0作为我的Web框架。
我的基本问题是我无法使用合并操作将重复记录添加到连接表中。MERGE 适用于添加记录,直到拥有键已存在,之后它只会更新连接表。我知道这是它应该工作的方式,但即使拥有密钥有重复,我也需要添加新记录。这将允许我将不同的项目存储在同一文件夹中。
我在这里浏览了其他一些问题,例如:
使用jpa进行可连接设置的onetomany单向
这说明了在连接表中将一个实体添加到另一个实体需要什么,但我需要更多地了解如何正确地将添加的实体持久化或将其合并到数据库中。
文件夹实体类:
@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);
}
....
....
Project 实体类是预先存在的代码,如果可能的话,我根本不想修改:
@Entity
@Table(name = "PROJECTS")
public class Projects {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int projectid;
private String projectName;
private String projectDescription;
@Temporal(javax.persistence.TemporalType.DATE)
private Date startDate;
@Temporal(javax.persistence.TemporalType.DATE)
private Date endDate;
private String commnts;
// foreign keys to parent tables
private int fk_countryid;
private int fk_companyid;
private int fk_employeeid;
@ManyToOne(optional = true)
@JoinColumn(name = "countryid")
private Country country;
....
....
然后,我使用两个html选择列表来选择projectid和proclassid的值,这两个值使用JSF管理的bean调用以下方法:
public String makeProClassRecord() {
newProClass = new ProjectClassifications(proclassid, projectid);
newProject = proServ.findByProjectId(projectid);
newProClass.addProject(newProject);
facade.update(newProClass);
//facade.save(newProClass);
return showProclass();
}
我的问题是:
MERGE是将记录添加到连接表中的正确操作吗?
2) 有没有办法使用 MERGE 添加包含重复键(在连接表中表示为新记录的外键)的记录?
3)应该使用PERSIST来实现问题2吗?
4) 为联接表本身创建一个实体并简单地使用PERSIST方法插入记录会更好吗?
多谢
所以我几周前自己解决了这个问题,并考虑分享答案。我没有对任何目标实体进行合并或持久化操作,而是创建了一个Join表和从项目实体到下面的ProjectFileSystem连接表实体的单向OneToMan关系,并简单地使用该实体进行持久化操作。我需要为不同的项目添加重复的文件夹(或将许多项目存储在一个文件夹项下),因此在实际连接表实体中而不是从目标实体中执行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();
}