https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/Interceptor.html 表示 onPrepareStatement(String sql) 已弃用。如果您希望检查和更改 SQL 语句,请改为提供 StatementInspector。
但我不清楚如何在应用程序级别的 Hibernate 中配置 StatementInspector (我不想在每个 Hibernate 会话级别设置它)。
注册
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
对象引用。
不要那样做)
您只需要两件事:
属性名称=“hibernate.session_factory.statement_inspector”值=“完全限定类名”
利润!
您可以在 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;
});
}
}
为了使其正常工作,您必须引导 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
,并且您的应用程序应该仍然可以正常工作。
一切就绪!
事情并没有太大变化——基本上有些东西被重命名了,所以从你在网上找到的旧的“拦截器”代码示例中,你只需要适应这些名称更改。如果您手动构建 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 相比