Как получить сгенерированный JPA запрос SQL?

Я использую спецификацию JPA и Hibernate в качестве своего поставщика. Мне нужно как-то взять сгенерированный SQL-запрос, который отправляется в БД (печатается в sysout) и сохраняет его как простую строку.

Есть ли способ сделать это?

ИЗМЕНИТЬ

Позвольте мне сделать это более ясным: мне не нужен журнал спящего режима. Мне нужно выполнить один и тот же запрос в другой БД. Поэтому мне нужно получить SQL-запрос как есть и удерживать его в обычной переменной String.

Изменить 2

Есть ли утилита, которую я могу предоставить ей bean, и она автоматически сгенерирует запрос Insert? могу ли я как-то использовать Hibernate beans здесь? Я знаю, что это сложный комплекс.

Спасибо,

Idob

Ответ 1

Создайте bean, как это.

@Bean
public JpaVendorAdapter jpaVendorAdapter(){
    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    jpaVendorAdapter.setGenerateDdl(true);
    jpaVendorAdapter.setShowSql(true);

    return jpaVendorAdapter;
}

Если вы используете Spring Boot, добавьте его где-нибудь в @Configuration.

Журналы, созданные из этого, исполняются в Workbench MySQL. Вы заявили, что используете JPA и Hibernate. Нет другого способа, кроме если поддерживаемая вами база данных поддерживается JPA. В этом случае вы можете реализовать AbstractJpaVendorAdapter.

Ответ 3

Если я вас правильно понимаю, вы хотите получить запрос вставки, который Hibernate выполняется в одной базе данных, и с помощью кода запустить его в другой базе данных с помощью entityManager#executeUpdate или аналогичного.

Hibernate не предоставляет сгенерированный запрос, так как он специфичен для диалекта целевой базы данных. Так что даже если бы получить запрос на вставку, это может быть бессмысленно.

Однако в вашем случае вы можете создать два соединения с базой данных (через два DataSource или EntityManagerFactory независимо от вашего случая) и дважды вызвать dao.persist(entity) для обеих баз данных, и позволить Hibernate обрабатывать часть построения запроса.

Изменение: Под запросом я имею в виду собственный запрос здесь, HQL-запрос будет одинаковым для обеих баз данных. Надеюсь, это поможет.

Ответ 4

Простой ответ на ваш вопрос: Нет. То, что вы хотите сделать, - это то, что многие разработчики также хотели бы сделать, но это не было частью спецификации JPA, и, следовательно, способность получить сгенерированный SQL будет зависеть от того, что поставщик решил сделать. Используя Hibernate, единственный способ получить SQL - это через журнал.

Ответ 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, вы можете преобразовать его в SQL с помощью QueryTranslator.

// 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();