我已找到several questions about这个,但没有一个完整地解释问题,以及如何调试它 - 答案都是轶事。
问题是在Play 1.2.4 JPA测试中,当我save()
模型时,我收到此异常:
org.hibernate.HibernateException:找到两个相同的表示 集合:models.Position.projects
我想知道:
Here is a reproduction of the problem on github。我有四个实体:
@Entity
public class Person extends Model {
public String name;
@OneToMany(cascade = CascadeType.ALL)
public List<Position> positions;
}
@Entity
public class Position extends Model {
public Position(){}
public Position(Company companies) {
this.companies = companies;
this.projects = new ArrayList<Project>();
}
@OneToOne
public Company companies;
@ManyToOne
public Person person;
@OneToMany
public List<Project> projects;
}
@Entity
public class Company extends Model {
public String name;
}
@Entity
public class Project extends Model {
public Project(){}
public Project(String field, String status){
this.theField = field;
this.status = status;
}
@ManyToOne
public Position position;
public String theField;
public String status;
}
我的持久性代码:
Company facebook = new Company();
facebook.name = "Facebook";
facebook.save();
Company twitter = new Company();
twitter.name = "Twitter";
twitter.save();
Person joe = new Person();
joe.name = "Joe";
joe.save();
joe.positions = new ArrayList<Position>();
Position joeAtFacebook = new Position(facebook);
joeAtFacebook.projects.add(new Project("Stream", "Architect"));
joeAtFacebook.projects.add(new Project("Messages", "Lead QA"));
joe.positions.add(joeAtFacebook);
Position joeAtTwitter = new Position(twitter);
joeAtTwitter.projects.add(new Project("Steal stuff from Facebook", "CEO"));
joe.positions.add(joeAtTwitter);
joe.save();
顺便说一句,我已经尝试过添加Play associations module作为一个人的建议,但它似乎没有帮助。
我看到确实创建的表在某种意义上是重复的:
我有一个person_position
表和一个position table
,其中两个都包含相似的字段:person_position
包含Person_id
和positions_id
,而position
1}}表包含id
(表示位置ID),person_id
和companies_id
。所以我理解我的模型定义会创建某种非预期的冗余,但我真的不明白如何解决它。
我认为这可能与双向映射有关,但这里是branch where the model is uni-directional(我删除了一些反向引用) - 问题仍然存在。
答案 0 :(得分:9)
据我所知,错误是由以下任意组合引起的:
mappedBy
注释中缺少/缺少@OneToMany
参数。此参数应该接收目标模型中引用该模型的字段的名称。 - org.hibernate -> hibernate-core 3.6.8.Final:
force: true
对我来说,上述步骤解决了问题。
实际上它是hibernate中的一个错误,因为它在持久化对象时被抛出,而它实际上意味着在创建模式时应该检测到的“设计时”问题。
我以前调试的步骤:
答案 1 :(得分:7)
尝试
@OneToMany(mappedBy="position")
public List<Project> projects;
答案 2 :(得分:1)
首先,我认为你错过了最后一行:
joe.positions.add(joeAtTwitter);
第二: 我认为你不应该这样做
joe.positions = new ArrayList<Position>();
而是将Person
更改为:
@Entity
public class Person extends Model {
public String name;
@OneToMany(cascade = CascadeType.ALL)
public List<Position> positions = new ArrayList<Position>();
}
它将解决您的问题,而且这是一种最佳实践,一般使用空集合而不是null
值(请参阅Effective Java),特别是使用Hibernate托管对象。阅读第一段here,了解为什么最好使用空集合进行初始化。
现在我认为发生的事情是:当你调用joe.save()
你已经管理了对象(通过Hibernate)然后你用新的集合覆盖了一个属性,我无法理解为什么你得到的错误是关于model.Position.projects
,但我认为就是这种情况。