如何获取JPA生成的SQL查询?

时间:2013-01-16 12:51:36

标签: jpa spring-data-jpa

我使用JPA规范和Hibernate作为我的供应商。我需要以某种方式将生成的SQL Query发送到DB(打印到sysout)并将其保存为一个简单的字符串。

有办法做到这一点吗?

修改

让我更清楚一点:我不需要休眠日志。我需要能够在不同的DB上执行相同的查询。因此,我需要按原样获取SQL查询,并将其保存在普通的String变量中。

修改2

是否有一个util,我可以为它提供一个bean,它会自动生成一个Insert查询?我能以某种方式在这里使用Hibernate bean吗?我知道这是一个节拍复杂。

谢谢,

Idob

6 个答案:

答案 0 :(得分:13)

像这样创建一个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。

答案 1 :(得分:1)

您必须启用log4j日志记录并为Hibernate添加一个appender以显示查询。

这已在此处描述:How to print a query string with parameter values when using Hibernate

答案 2 :(得分:1)

你的问题的简单答案是否定的。你想要做的是许多开发人员也想做的事情,但它不是JPA规范的一部分,因此获得生成的SQL的能力将取决于供应商决定这样做。使用Hibernate获取SQL的唯一方法是通过日志。

答案 3 :(得分:1)

如果我理解正确,你想获得在一个数据库上执行Hibernate的插入查询,并通过代码,通过entityManager#executeUpdate或类似的方式在另一个数据库上运行它。

Hibernate不公开生成的查询,因为它特定于目标数据库的方言。所以,即使要获得插入查询,也可能毫无意义。

但是在您的情况下,您可以创建两个数据库连接(通过两个DataSourceEntityManagerFactory无论如何)并为两个数据库调用dao.persist(entity)两次,并让Hibernate处理查询构造部分。

编辑:通过查询我的意思是本地查询,两个数据库的HQL查询都是相同的。 希望它有所帮助。

答案 4 :(得分:0)

尝试在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;
    }
}

答案 5 :(得分:0)

我不知道生成查询的含义,但是如果您使用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();