如何在 Hibernate 中配置 StatementInspector?

问题描述 投票:0回答:5

https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/Interceptor.html 表示 onPrepareStatement(String sql) 已弃用。如果您希望检查和更改 SQL 语句,请改为提供 StatementInspector。

但我不清楚如何在应用程序级别的 Hibernate 中配置 StatementInspector (我不想在每个 Hibernate 会话级别设置它)。

java sql hibernate jdbc inspect
5个回答
7
投票

注册

StatementInspector
的最佳方法是使用
hibernate.session_factory.statement_inspector
配置属性。

这样,无论您是使用 JPA(例如 Spring Data JPA)还是本机 Hibernate(例如带有

HibernateTranscationManager
LocalSessionFactoryBean
的 Spring)引导 Hibernate 都无关紧要。

因此,您可以通过

hibernate.session_factory.statement_inspector
JPA 配置文件提供
persistence.xml

<property
    name="hibernate.session_factory.statement_inspector"
    value="com.vladmihalcea.book.hpjp.hibernate.logging.inspector.SqlCommentStatementInspector"
/>

或者,如果您使用 Spring,您也可以通过编程方式设置

hibernate.session_factory.statement_inspector

@Bean
public LocalSessionFactoryBean sessionFactory() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource());
    sessionFactory.setPackagesToScan({
        "com.vladmihalcea.books.high.performance.java.persistence"
    });
    sessionFactory.setHibernateProperties(hibernateProperties());

    return sessionFactory;
}

@Bean
public PlatformTransactionManager hibernateTransactionManager() {
    HibernateTransactionManager transactionManager
      = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory().getObject());
    return transactionManager;
}

private final Properties hibernateProperties() {
    Properties hibernateProperties = new Properties();
    hibernateProperties.setProperty(
      "hibernate.session_factory.statement_inspector", 
      SqlCommentStatementInspector.class
    );
    hibernateProperties.setProperty(
      "hibernate.dialect", 
      "org.hibernate.dialect.H2Dialect"
    );

    return hibernateProperties;
}

请注意,

hibernate.session_factory.statement_inspector
设置可以采用代表实现
String
接口的完全限定类的
StatementInspector
Class<? extends StatementInspector>
StatementInspector
对象引用。


4
投票

不要那样做)

您只需要两件事:

  1. 向 persistence.xml 添加属性:

属性名称=“hibernate.session_factory.statement_inspector”值=“完全限定类名”

  1. 通过实现 org.hibernate.resource.jdbc.spi.StatementInspector 接口来编写监听器类。

利润!


1
投票

您可以在 Spring 中使用

HibernatePropertiesCustomizer

@Configuration
public class HibernateConfig {

    @Bean
    public HibernatePropertiesCustomizer configureStatementInspector() {
        return (properties) -> properties.put(AvailableSettings.STATEMENT_INSPECTOR, (StatementInspector) sql -> {
            // figure out what to return
            return sql;
        });
    }
}

0
投票

为了使其正常工作,您必须引导 Hibernate。为此:

在主类中,找到 EntityManagerFactory 实例。它可能看起来像这样:

public static final EntityManagerFactory EMPFAC = Persistence.createEntityManagerFactory("jpa")

暂时保留该行。在其上方添加以下内容:

private static StandardServiceRegistryBuilder servReg = new StandardServiceRegistryBuilder();
static {
    //Do this for every property in persistence.xml
    servReg.applySetting("hibernate.connection.url", "jdbc://myurl://www.example.org");
}

servReg.applySetting()
中的每个属性添加
persistence.xml
。然后,在其下方添加以下内容:

private static MetadataSources sources = new MetadataSources(servReg.build());
static {
    // Do this for every pojo with JPA annotations
    sources.addAnnotatedClass(Pojo.class);
}

为应用程序中每个带 JPA 注释的 pojo 添加

sources.addAnnotatedClass()
。到这里就差不多完成了。现在创建一个实现
StatementInspector
的类,如下所示:

public class Inspector implements StatementInspector {

    private static final long serialVersionUID = 5545844969759630544L;

   @Override
   public String inspect(String select) {
       // modify string here
       return select;
   }
}

最后,返回到主应用程序类,并在注册 pojo 的静态块下方添加以下内容:

public static final SessionFactory EMPFAC = sources.buildMetadata().getSessionFactoryBuilder().applyStatementInspector(new Inspector()).build();

现在您可以返回

persistence.xml
并删除那里的属性声明。如果您还没有删除您的
public static final EntityManager
声明(您已将其替换为 SessionFactory)。

编辑:您实际上可以删除

persistence.xml
,并且您的应用程序应该仍然可以正常工作。

一切就绪!


0
投票

事情并没有太大变化——基本上有些东西被重命名了,所以从你在网上找到的旧的“拦截器”代码示例中,你只需要适应这些名称更改。如果您手动构建 SessionFactory (像我一样),您可以这样做:

public class MyInspector implements StatementInspector {
   @Override
   public String inspect(String sql) {
       System.out.println(sql); // or whatever you want to do
       return sql;
   }
}

然后,在设置 SessionFactory 时,插入它的方式与之前插入拦截器的方式非常相似

Configuration config = new Configuration();
config.setProperty("hibernate.connection.username", "myusername");
// ...
config.addAnnotatedClass(SomeClass.class);
// ...
config.setStatementInspector(new MyInspector()); // !!!!!!!!!!!!!!
SessionFactory mySessionFactory = config.buildSessionFactory();
// do something with the session factory

参见6.1中的setInterceptor 与 6.2 中的 setStatementInspector 相比

© www.soinside.com 2019 - 2024. All rights reserved.