如何从 Hibernate Criteria API 获取 SQL(*不是* 用于日志记录)

2022-08-31 12:45:32

有没有办法从休眠中获取(要生成的)SQL?Criteria

理想情况下,我会有这样的东西:

Criteria criteria = session.createCriteria(Operator.class);

... build up the criteria ...
... and then do something like ...

String sql = criteria.toSql()

(But this of course does not exist)

然后,我们的想法是将SQL用作巨大的“MINUS”查询的一部分(我需要找到2个相同架构之间的差异 - 在结构上相同,而不是在数据中 - 并且Hibernate不支持MINAS)

(顺便说一句,我知道我可以从日志文件中检查SQL)


答案 1

以下是获取SQL的“另一种”方法:

CriteriaImpl criteriaImpl = (CriteriaImpl)criteria;
SessionImplementor session = criteriaImpl.getSession();
SessionFactoryImplementor factory = session.getFactory();
CriteriaQueryTranslator translator=new CriteriaQueryTranslator(factory,criteriaImpl,criteriaImpl.getEntityOrClassName(),CriteriaQueryTranslator.ROOT_SQL_ALIAS);
String[] implementors = factory.getImplementors( criteriaImpl.getEntityOrClassName() );

CriteriaJoinWalker walker = new CriteriaJoinWalker((OuterJoinLoadable)factory.getEntityPersister(implementors[0]), 
                        translator,
                        factory, 
                        criteriaImpl, 
                        criteriaImpl.getEntityOrClassName(), 
                        session.getLoadQueryInfluencers()   );

String sql=walker.getSQLString();

答案 2

我使用Spring AOP完成了类似的事情,因此我可以获取应用程序中任何查询运行的sql,参数,错误和执行时间,无论是HQL,Criteria还是本机SQL。

这显然是脆弱的,不安全的,可能会随着Hibernate等的变化而中断,但它说明了可以获得SQL:

CriteriaImpl c = (CriteriaImpl)query;
SessionImpl s = (SessionImpl)c.getSession();
SessionFactoryImplementor factory = (SessionFactoryImplementor)s.getSessionFactory();
String[] implementors = factory.getImplementors( c.getEntityOrClassName() );
CriteriaLoader loader = new CriteriaLoader((OuterJoinLoadable)factory.getEntityPersister(implementors[0]),
    factory, c, implementors[0], s.getEnabledFilters());
Field f = OuterJoinLoader.class.getDeclaredField("sql");
f.setAccessible(true);
String sql = (String)f.get(loader);

将整个东西包装在尝试/捕获和使用中,风险自负。


推荐