【发布时间】:2021-11-01 17:17:44
【问题描述】:
我的目标是拦截由 JPA 生成的“原始”SQL 查询,其下带有 Hibernate(这个原始请求非常复杂,通过 JPA 标准 API 生成,有时需要快速更改,所以我不能只是移动到本机 SQL),对其进行一些更改(Hibernate 无法做的更改,即删除连接实体表中不必要的列),然后执行它并映射到原始查询所针对的相同实体结构。 到目前为止我的进展:
- 从 JPA TypedQuery 获得 Hibernate 查询
org.hibernate.Query hquery = typedQuery.unwrap(org.hibernate.Query.class);
- 从 hql 请求中获得原生 SQL(可以从实体管理器的 hquery 对象中提取所提供方法的所有必要参数):
private String hqlToSql (SessionFactory sessionFactory, String hqlQueryText, EntityGraphQueryHint egqh) {
QueryTranslatorFactory qtf = new ASTQueryTranslatorFactory();
SessionFactoryImplementer sfi = (SessionFactoryImplementer) sessionFactory;
QueryTranslator translator = qtf.createQueryTranslator(hqlQueryText, hqlQueryText, Collections.EMPTY_MAP, sfi, egqh);
translator.compile(Collections.EMPTY_MAP, false);
return translator.getSQLString();
}
- 从 hquery 中提取的查询参数映射,名称如“param0”、“param1”等。
我目前的挑战:
-
我提取的 SQL 字符串与执行原始查询期间输出的休眠日志记录完全相同。它有利于记录,但不适用于实际执行 - 它有问号 (?) 而不是名称参数(如:param0)或顺序(如?1)。我宁愿获得 Hibernate 生成的实际查询,而不必替换我的代码中的问号,也不必担心生成的 JPA/Hibernate 查询字符串中的潜在问号。有什么方法可以获取 SQL,因为它会去 JDBC 进行实际的 DB 请求?
-
我仍然需要将请求结果映射到实体结构。我不能只要求 Hibernate 返回此请求所针对的实体,因为生成的查询的字段别名与实体字段到表列的映射完全不同。因此,我需要将请求结果映射作为本机 SQL JPA 或 Hibernate 请求将接受作为映射的对象,或者作为将获取原始查询结果列表并返回实体对象列表的函数。我如何获得(更准确地说,从 Hibernate 结构中提取)这样的请求结果映射?
【问题讨论】:
-
查看实体图和命名实体图。您可以指定它应该加载的内容并为您的子实体指定子图。
-
实体图已经应用,它们限制了要加载的实体,我需要限制连接实体的字段(以及这些字段的相应数据库列)。