如何获取 JPA 生成的 SQL 查询?
Posted
技术标签:
【中文标题】如何获取 JPA 生成的 SQL 查询?【英文标题】:How to get the JPA generated SQL query? 【发布时间】:2012-12-30 19:16:11 【问题描述】:我使用 JPA 规范和 Hibernate 作为我的供应商。我需要以某种方式获取发送到数据库的生成的 SQL 查询(打印到 sysout)并将其保存为一个简单的字符串。
有没有办法做到这一点?
编辑
让我更清楚一点:我不需要休眠日志。我需要能够在不同的数据库上执行相同的查询。因此,我需要按原样获取 SQL 查询,并将其保存在一个普通的 String 变量中。
编辑 2
是否有一个实用程序可以提供一个 bean,它会自动生成一个插入查询?我可以在这里以某种方式使用 Hibernate bean 吗?我知道这是一个节拍复合体。
谢谢,
伊多布
【问题讨论】:
编辑你的问题,不太清楚你问的是spring data jpa模块,spring可以在没有spring data的情况下使用jpa 你找到解决办法了吗? 看起来没有一个干净的解决方案。您也许可以通过参数将 EntityManager 传递给规范实现,然后使用此处找到的代码 antoniogoncalves.org/2012/05/24/… @ido-barash 您是否获得了“我需要按原样获取 SQL 查询,并将其保存在普通字符串变量中”的解决方案。 ?如果是,请告诉我。 没有。我放弃了 【参考方案1】:像这样创建一个 bean。
@Bean
public JpaVendorAdapter jpaVendorAdapter()
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setGenerateDdl(true);
jpaVendorAdapter.setShowSql(true);
return jpaVendorAdapter;
如果您使用 Spring Boot,请将其添加到您的 @Configuration 中。
由此创建的日志可在 mysql 工作台中执行。 您说您正在使用 JPA 和 Hibernate。除非您支持的数据库受 JPA 支持,否则别无他法。在这种情况下,您可以实现一个 AbstractJpaVendorAdapter。
【讨论】:
酷。能够在我的控制台中看到 sql 语句 :) 如果我还想查看参数值?【参考方案2】:您的问题的简单答案是否定的。您想要做的是许多开发人员也想做的事情,但它不是 JPA 规范的一部分,因此获取生成的 SQL 的能力将取决于供应商决定这样做。使用 Hibernate 获取 SQL 的唯一方法是通过日志。
【讨论】:
通过 Hibernate 的示例找到了这个。 ***.com/questions/554481/… 。使用 Hibernate 可以在 String 中获取 SQL【参考方案3】:您必须启用 log4j 日志记录并为 Hibernate 添加一个附加程序以显示查询。
这里已经描述过了:How to print a query string with parameter values when using Hibernate
【讨论】:
这不是我问的! 我需要将查询作为字符串获取以备后用。不在日志中查看。【参考方案4】:如果我对您的理解正确,您希望获取 Hibernate 在一个数据库上执行的插入查询,并通过代码通过entityManager#executeUpdate
或类似方法在另一个数据库上运行它。
Hibernate 不会公开生成的查询,因为它特定于目标数据库的方言。因此,即使要获得插入查询,也可能毫无意义。
但是,在您的情况下,您可以创建两个数据库连接(通过两个DataSource
或EntityManagerFactory
在您的情况下)并为两个数据库调用两次dao.persist(entity)
,然后让 Hibernate 处理查询构造部分。
编辑:这里的查询是指本地查询,两个数据库的 HQL 查询是相同的。 希望对您有所帮助。
【讨论】:
【参考方案5】:尝试在 LocalContainerEntityManagerFactoryBean 的实例中添加属性,它对我有用:-
@EnableJpaRepositories(basePackages = "org.common.persistence.dao")
public class PersistenceJPAConfig
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory()
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] "org.common.persistence.model" );
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
final Properties additionalProperties()
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("showSql", "true");
hibernateProperties.setProperty("hibernate.show_sql", "true");
hibernateProperties.setProperty("hibernate.format_sql", "true");
hibernateProperties.setProperty("hibernate.query.substitutions", "false");
return hibernateProperties;
【讨论】:
【参考方案6】:我不知道生成的查询是什么意思,但是如果您使用 Hibernate 并且拥有 javax.persistence.Query query
,您可以很容易地获得 HQL 字符串(对于 EclipseLink,它是类似的)。如果你有 HQL,你可以用 QueryTranslator 将它翻译成 SQL。
// Get HQL
String hqlQueryString = query.unwrap(org.hibernate.query.Query.class).getQueryString();
// Translate HQL to SQL
ASTQueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
SessionImplementor hibernateSession = em.unwrap(SessionImplementor.class);
QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator("", hqlQueryString, Collections.emptyMap(), hibernateSession.getFactory(), null);
queryTranslator.compile(Collections.emptyMap(), false);
String sqlQueryString = queryTranslator.getSQLString();
【讨论】:
以上是关于如何获取 JPA 生成的 SQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Spring Boot JPA 执行具有 INTERVAL 子句的本机 SQL 查询?
JPA 一个实体中的两个惰性集合 - 如何运行 JPA 查询以获取实体和只有一个集合