Java “如何调试”;找到了同一集合的两个表示形式;?
我发现了这一点,但没有一个完整地解释了这个问题,以及如何调试它-答案都是轶事 问题在于,在Play 1.2.4 JPA测试中,当我Java “如何调试”;找到了同一集合的两个表示形式;?,java,hibernate,jpa,orm,playframework,Java,Hibernate,Jpa,Orm,Playframework,我发现了这一点,但没有一个完整地解释了这个问题,以及如何调试它-答案都是轶事 问题在于,在Play 1.2.4 JPA测试中,当我save()a模型时,会出现此异常: org.hibernate.HibernateException:找到了相同的两个表示形式 集合:models.Position.projects 我想知道: 是否有与游戏无关的一般问题文档?问题出在hibernate上,但谷歌在这方面的很多结果都在Play应用程序中 有哪些基本的最佳实践可以避免这个问题 它是由玩耍引起的吗?还是
save()
a模型时,会出现此异常:
org.hibernate.HibernateException:找到了相同的两个表示形式
集合:models.Position.projects
我想知道:
@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;
}
@实体
公共类人扩展模型{
公共字符串名称;
@OneToMany(级联=级联类型.ALL)
公开名单职位;
}
@实体
公共类位置扩展模型{
公共位置(){}
公众职位(公司){
这是指公司;
this.projects=new ArrayList();
}
@奥内托内
上市公司;
@许多酮
公众人物;
@独身癖
公开项目清单;
}
@实体
上市公司扩展模型{
公共字符串名称;
}
@实体
公共类项目扩展模型{
公共项目(){}
公共项目(字符串字段、字符串状态){
this.theField=字段;
这个状态=状态;
}
@许多酮
公共职位;
公共领域;
公共字符串状态;
}
和我的持久性代码:
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();
Company facebook=新公司();
facebook.name=“facebook”;
facebook.save();
公司推特=新公司();
twitter.name=“twitter”;
twitter.save();
人乔=新人();
joe.name=“joe”;
joe.save();
joe.positions=newarraylist();
职位joeAtFacebook=新职位(facebook);
添加(新项目(“流”、“架构师”);
添加(新项目(“消息”,“领导QA”);
joe.positions.add(joeAtFacebook);
职位joeAtTwitter=新职位(twitter);
添加(新项目(“从Facebook偷东西”、“CEO”);
joe.positions.add(joeatwitter);
joe.save();
顺便说一句,我试着按照一个人的建议添加,但似乎没有帮助
我发现创建的表确实在某种意义上是重复的:
我有一个person\u position
表和一个position表,其中都包含类似的字段:person\u position
包含person\u id
和positions\u id
,而position
表包含id
(意思是位置id),person\u id
,和公司id
。所以我知道我的模型定义产生了某种非预期的冗余,但我真的不知道如何解决它
我认为这可能与双向映射有关,但这里有一个问题(我删除了一些反向引用),问题仍然存在。试试看
@OneToMany(mappedBy="position")
public List<Project> projects;
@OneToMany(mappedBy=“position”)
公开项目清单;
据我所知,错误是由以下任意组合引起的:
@OneToMany
注释上缺少/缺少mappedBy
参数。此参数应接收目标模型中引用此模型的字段的名称
- 旧的hibernate-播放1.2.4附带hibernate 3.6.1。。。升级到3.6.8似乎解决了另一个此类问题(只需将以下内容添加到dependencies.yml和play deps)
-org.hibernate->hibernate核心3.6.8.最终版本:
force:true
对我来说,上述步骤解决了问题
它实际上是hibernate中的一个bug,因为它是在持久化对象时抛出的,而它实际上意味着在创建模式时应该检测到的“设计时”问题
我用来调试的步骤:
- 写了一个测试,重现了这个问题
- 补充道-我不确定它是否解决了问题的一部分,还是使问题变得更糟
- 通过hibernate代码进行调试,并意识到这可能表明存在hibernate问题,而不是用户/配置错误
- 注意到hibernate在3.6.1之后有很多错误修复版本,决定试试运气并升级
- 同样重要的是,清理tmp文件夹不会对编译的JAR造成伤害,在进行重大更改(如升级hibernate版本)后,可能值得清理它
首先,我想你错过了最后一行之前的第一行:
joe.positions.add(joeAtTwitter);
第二:
我认为你不应该这样做
joe.positions = new ArrayList<Position>();
它将解决您的问题,而且它是一种最佳实践,通常使用空集合而不是null
value(请参见有效Java),特别是用于处理Hibernate托管对象。阅读第一段,了解为什么最好使用空集合初始化
现在我想发生的是:当您调用joe.save()
使对象由Hibernate管理,然后使用新集合覆盖属性时,我不理解为什么您得到的错误是关于model.Position.projects
,但我想情况就是这样。我的猜测-级联问题。添加一个职位,该职位会添加两个项目,然后joe.save()可能会导致添加两次该职位。使用级联选项并报告:)@KenEgozi-级联选项是否影响我的表的生成?因为我有一个重复的表结构本身。。。(我把细节放在问题中)@KenEgozi-通过升级hibernate版本解决-见我的答案。谢谢,谢谢你的帮助。也许我在上面的回答中没有说清楚,但是指定mappedBy属性并从hibernate 3.6.1升级到3.6.8解决了这个问题
@Entity
public class Person extends Model {
public String name;
@OneToMany(cascade = CascadeType.ALL)
public List<Position> positions = new ArrayList<Position>();
}