public static String from(Query query) {
        if (query instanceof SqmInterpretationsKey.InterpretationsKeySource &&
            query instanceof QueryImplementor &&
            query instanceof QuerySqmImpl) {
            QueryInterpretationCache.Key cacheKey = SqmInterpretationsKey.createInterpretationsKey((SqmInterpretationsKey.InterpretationsKeySource) query);
            QuerySqmImpl querySqm = (QuerySqmImpl) query;
            Supplier buildSelectQueryPlan = () -> ReflectionUtils.invokeMethod(querySqm, "buildSelectQueryPlan");
            SelectQueryPlan plan = cacheKey != null ? ((QueryImplementor) query).getSession().getFactory().getQueryEngine()
                .getInterpretationCache()
                .resolveSelectQueryPlan(cacheKey, buildSelectQueryPlan) :
                (SelectQueryPlan) buildSelectQueryPlan.get();
            if (plan instanceof ConcreteSqmSelectQueryPlan) {
                ConcreteSqmSelectQueryPlan selectQueryPlan = (ConcreteSqmSelectQueryPlan) plan;
                Object cacheableSqmInterpretation = ReflectionUtils.getFieldValueOrNull(selectQueryPlan, "cacheableSqmInterpretation");
                if (cacheableSqmInterpretation == null) {
                    DomainQueryExecutionContext domainQueryExecutionContext = DomainQueryExecutionContext.class.cast(querySqm);
                    cacheableSqmInterpretation = ReflectionUtils.invokeStaticMethod(
                        ReflectionUtils.getMethod(
                            ConcreteSqmSelectQueryPlan.class,
                            "buildCacheableSqmInterpretation",
                            SqmSelectStatement.class,
                            DomainParameterXref.class,
                            DomainQueryExecutionContext.class
                        ),
                        ReflectionUtils.getFieldValueOrNull(selectQueryPlan, "sqm"),
                        ReflectionUtils.getFieldValueOrNull(selectQueryPlan, "domainParameterXref"),
                        domainQueryExecutionContext
                    );
                }
                if (cacheableSqmInterpretation != null) {
                    JdbcSelect jdbcSelect = ReflectionUtils.getFieldValueOrNull(cacheableSqmInterpretation, "jdbcSelect");
                    if (jdbcSelect != null) {
                        return jdbcSelect.getSql();
                    }
                }
            }
        }
        return ReflectionUtils.invokeMethod(query, "getQueryString");
    }
@Test
    public void testCriteriaAPI() {
        doInJPA(entityManager -> {
            CriteriaBuilder builder = entityManager.getCriteriaBuilder();

            CriteriaQuery<PostComment> criteria = builder.createQuery(PostComment.class);

            Root<PostComment> postComment = criteria.from(PostComment.class);
            Join<PostComment, Post> post = postComment.join("post");

            criteria.where(
                builder.like(post.get("title"), "%Java%")
            );

            criteria.orderBy(
                builder.asc(postComment.get("id"))
            );

            Query criteriaQuery = entityManager.createQuery(criteria);

            String sql = SQLExtractor.from(criteriaQuery);

            assertNotNull(sql);

            LOGGER.info(
                "The Criteria API query: [\n{}\n]\ngenerates the following SQL query: [\n{}\n]",
                criteriaQuery.unwrap(org.hibernate.query.Query.class).getQueryString(),
                sql
            );
        });
    }