Java 为什么hibernate会生成约500个SQL查询?
在一个遗留项目中尝试优化Hibernate 4.2生成的MySQ慢速查询时,我发现下面的代码生成了近500个包含许多重复项的SQL查询:Java 为什么hibernate会生成约500个SQL查询?,java,mysql,hibernate,Java,Mysql,Hibernate,在一个遗留项目中尝试优化Hibernate 4.2生成的MySQ慢速查询时,我发现下面的代码生成了近500个包含许多重复项的SQL查询: class MyDAO { public List<Message> findMessages() { Session session = MyHibernateUtils.openSession(); String queryStr = "SELECT DISTINCT m FROM Message m
class MyDAO {
public List<Message> findMessages() {
Session session = MyHibernateUtils.openSession();
String queryStr = "SELECT DISTINCT m FROM Message m "
+ " LEFT JOIN fetch m.types types "
+ " LEFT JOIN fetch m.mainType mainType "
+ " LEFT JOIN fetch m.place place "
+ " LEFT JOIN fetch m.building building "
+ " LEFT JOIN fetch m.city city "
+ " LEFT JOIN fetch m.kind kind "
+ " LEFT JOIN fetch m.domain domain "
+ " LEFT JOIN fetch m.action action "
+ " LEFT JOIN fetch m.customParameterA customParameterA "
+ " LEFT JOIN fetch m.customParameterB customParameterB "
+ " LEFT JOIN fetch m.scheduleEvents scheduleEvents "
+ " LEFT JOIN fetch m.comments comments "
+ " LEFT JOIN fetch m.messageLastActivities messageLastActivities "
+ " LEFT JOIN fetch m.customListA customListA "
+ " LEFT JOIN fetch m.childEvents childEvents "
+ " LEFT JOIN fetch m.parentEvent parentEvent "
+ " WHERE ...";
List<Message> messages;
try {
session.getTransaction().begin();
Query query = session.createQuery(queryStr);
query.setTimeout(10);
messages = query.list();
session.getTransaction().commit();
} catch (RuntimeException e) {
session.getTransaction().rollback();
throw e;
} finally {
session.close();
}
return messages;
}
}
如何避免出现如此多的SQL查询
我不知道这是否有帮助,但在实体之间有很多的关系
感谢您的帮助。根据您的关系设计,Fetch in@OneToMany和@ManyToMany的默认值是惰性的,这意味着当您调用getter方法时,hibernate将在子实体中加载相关记录,并执行另一个查询来加载该记录,例如:select*from foo,其中id=,所以,若加载的实体主实体包含许多子实体,比如ManyToMany或OneToMany,那个么您将在控制台中看到许多查询。 若要取消这些查询,可以将Fetch设置为EAGER,但在优化时不建议这样做
@Entity
public class MainEntity {
@ManyToMany(Fetch = FetchType.EAGER)
public List<Foo> foos;
}
您应该检查hibernate生成的查询,以查看哪个表经常被访问 您还必须加入由相关实体关联的获取实体,请参见此处: 我个人更喜欢使用带注释的@BatchSize进行惰性加载,以保持惰性查询计数较小。仅使用2的批处理大小就可以将查询计数减半
还可以看看@Cache注释,它可以显著减少查询计数。想想所有几乎是静态的东西,比如城市/建筑/类型/领域等等ORM框架大部分时间都是这样工作的。。。他们需要从id=1的表中触发一个额外的SELECT*,以查找相关的entiy@RaymondNijland不,他们没有。好吧,在最坏的情况下,他们会这样做,但这在大多数情况下是可以避免的,当然在Hibernate中也是可以避免的。只有非常幼稚的ORM才会这样做,因为它会破坏性能,使框架变得毫无价值。至于OP,启用Hibernate的SQL日志环顾四周,我不记得它是如何完成的,我不记得会执行什么查询。这将允许您确定原因,这可能只是您需要修复的单个N+1查询。true@Kayaman..@Kayaman是的,他们是这样做的,raymond是对的。Eagar抓取通常需要额外的操作,如添加注释或jointhank you@Moodi以获取响应!使用left join fetch是否已经强制每个*ToMany依赖项都被急切地获取?是的,它将获取属性。您可以用于子实体中的实体。正确!谢谢@dognose,在添加了一些缺失的相关实体之后,查询的数量大大减少了。