hibernate在select查询中生成过多的连接数

时间:2014-11-06 00:54:23

标签: java mysql spring hibernate jpa

在使用spring mvchibernate的{​​{1}}应用中,jpa正在使用 78个加入创建一个过于复杂的查询连接应该是必要的。我正在使用hibernate。为了简化问题和实验,我在相关实体中注释了许多属性,并且还将父类中的代码剪切并粘贴到子类中以减少继承量。这减少了应该包含在连接中的表的数量为8.但是当我在其中一个实体上尝试InhertanceType.JOINED时,hibernate会生成不应包含的连接。有人可以请我帮我隔离代码中的问题吗?

您可以查看应包含在连接中的8到12个类的类图 by clicking on this link。这是一个JPEG文件,您可以通过单击它在浏览器中放大。连接中可能只包含8到12个类,但 hibernate在连接中包含另外12个不相关的表,这是完全没必要的。为什么?


解答:

问题的原因是EntityManager.persist()类的持有数据类型的包名错误。因此,applicationService.java完成的select是错误包的同名实体的entitymanager

关于它的奇怪部分是,日食似乎没有抱怨不同的包装。该体系结构是select调用包含controllerservice layer的{​​{1}},然后调用applicationService.java图层,其中包含applicationServiceImpl.javarepository。错误的包位于repository.java但不包含在repositoryImpl.javaservice layer中。我不知道为什么eclipse没有抱怨这个。问题直到运行时才出现。

我认为弗拉德的回答是被接受的,因为他提供了几轮非常清晰且有用的解决方法。

2 个答案:

答案 0 :(得分:3)

虽然这种相互连接的设计从OOP的角度来看是有效的,但你必须记住,你正在处理关系数据库,因此过多的继承会损害性能。

解释联接

您当前的查询根实体是Person,并且提供的图表具有误导性,因为它没有说Person是LivingSubject,它是RimEmtity。

rimEntity.classCode标记为lazy但我看到Hibernate尝试外连接。这不应该发生,因为第二个选择应该加载,所以我怀疑代码和错误不同步,因为在CD类中找不到这种关联:

left outer join TS ivlts2_ on cd1_.VALID_TIME_HXITCE_HJID=ivlts2_.HJID

让我们再来一个@ManyToOne,LivingSubject.birthTime

left outer join TS ts5_ on person0_.birthTime_HJID=ts5_.HJID

所有这些都与整个Person类层次结构的@ManyToOne关联有关。

一种可能的“解决方案”:

尝试设置此属性:

hibernate.max_fetch_depth=0

这将禁用外部连接,然后Hibernate将使用其他选择,但这可能会对性能造成更大的影响。

使用auto-generated code and hbmddl是一个糟糕的设计决定。您的数据库模式应该由增量更新脚本生成,并且您的Hibernate映射应该将数据库表映射到域模型类。

拥有如此多的关系会对性能造成严重影响,因此没有解决问题的灵丹妙药。

您应首先设计db表和查询,然后确定哪个是最适合您应用程序需求的域模型。

答案 1 :(得分:1)

(代表问题作者发布了解决方案,将其移至答案帖)

问题的原因是applicationService.java类对于要保留的数据类型具有错误的程序包名称。因此,由select完成的entitymanager是同名错误包实体的select

奇怪的是,Eclipse似乎并没有抱怨其他软件包。该体系结构是,控制器调用包含applicationService.javaapplicationServiceImpl.java的服务层,然后调用包含repository.javarepositoryImpl.java的存储库层。错误的程序包位于服务层,但不在控制器层或存储库层。我不知道为什么Eclipse对此没有抱怨。该问题直到运行时才出现。

我将弗拉德的答案标记为已接受,因为他提供了几轮非常明确和有用的解决方法。