如何正确地将记录添加到jpa onetomany联接表

时间:2015-05-01 04:06:45

标签: java mysql hibernate jpa jpa-2.0

我正在开发一个文件系统,我有3张桌子。 PROJECTS表由项目名称,项目名称和其他详细信息组成(见下文)。这是一个现有的类和填充的模式,如果可能的话,我不想修改应用程序的这一部分。

文件夹表(称为ProjectClassification)由folderid和foldername组成,是单向onetomany关系的拥有方。

Project_Folders是一个连接表。我使用JPA 2.0(EclipseLink)和JSF 2.0作为我的Web框架。

我的基本问题是我无法使用合并操作将重复记录添加到连接表。 MERGE适用于添加记录,直到拥有密钥已存在,之后它将仅更新连接表。我知道这是它应该工作的方式但我需要添加新的记录,即使它们是拥有密钥的副本。这将允许我将不同的项目存储在同一个文件夹中。

我在这里查看了其他一些问题,例如:

onetomany unidirectional with jointable setup using jpa

这说明在连接表中将一个实体添加到另一个实体需要什么,但我需要了解更多关于如何正确地保留或将添加的实体合并到数据库的信息。

文件夹实体类:

@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调用以下的methoid:

public String makeProClassRecord() {
   newProClass = new ProjectClassifications(proclassid, projectid);
   newProject = proServ.findByProjectId(projectid);
   newProClass.addProject(newProject);


facade.update(newProClass);
//facade.save(newProClass);
    return showProclass();
}

我的问题是:

1)MERGE是否是用于将记录添加到连接表的正确操作?

2)有没有办法使用MERGE添加包含重复键的记录(外键在连接表中表示为新记录)?

3)应该使用PERSIST来解决问题2吗?

4)为连接表本身创建实体并简单地使用PERSIST方法插入记录会更好吗?

非常感谢

1 个答案:

答案 0 :(得分:0)

所以几个星期前我自己解决了这个问题并想到了分享答案。我没有在任何目标实体上执行合并或持久操作,而是从Project实体到下面的ProjectFileSystem连接表实体创建了一个Join表和单向OneToMany关系,并简单地使用该实体执行了持久操作。我需要为不同的项目添加重复的文件夹(或在单个文件夹项下存储许多项目),因此在实际的连接表实体中而不是从目标实体执行CRUD操作似乎更有效。希望这会有所帮助:

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

bean中的方法是:

$account = new Account(1);
$withdrawal = new Withdrawal($account, 50,'USD');
$withdrawal -> makeTransaction();