如何将 spring beans 注入休眠环境 RevisionListener
How to inject spring beans into the hibernate envers RevisionListener
我正在使用 Spring 5.1 和 Hibernate 5.3.9,包括 hibernate-envers。
我不知道如何将 spring bean 注入休眠环境自定义 RevisionListener。
我试过了
(@Service or @Component)
public class ExtendedRevisionListener implements RevisionListener {
@Autowired
private MyService myService;
void newRevision(Object revisionEntity){
myService.doSomething(...)
}
}
当然 class 包含在 @ComponentScan 包解析中。
一个问题是 myService 没有注入到监听器中。
在 hibernate-envers 文档中:
从 Hibernate Envers 5.3 开始,RevisionListener 现在支持依赖注入。
此功能取决于各种依赖框架,例如 CDI 和 Spring,以在 Hibernate ORM bootstrap 期间提供必要的实现以支持注入。如果没有提供符合条件的实现,将在没有注入的情况下构造 RevisionListener。
不幸的是,我还没有找到任何有效的例子。
@纳罗斯
我在 spring 持久性 JPA 中设置了 EntityMaganerFactoryBean
配置 -> entityManager =
新 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean()
10:49| DEBUG | SessionFactoryImpl.java 252 | Session factory constructed with filter configurations : {}
10:49| DEBUG | SessionFactoryImpl.java 253 | Instantiating session factory with properties: {hibernate.format_sql=true, awt.toolkit=sun.awt.windows.WToolkit, hibernate.id.new_generator_mappings=false, java.specification.version=1.8, logging.configuration=file:C:\wildfly16\standalone\configuration\logging.properties, sun.cpu.isalist=amd64, sun.jnu.encoding=Cp1250, sun.arch.data.model=64, org.jboss.resolver.warning=true, java.vendor.url=http://java.oracle.com/, javax.persistence.validation.mode=AUTO, sun.boot.library.path=C:\Program Files\Java\jdk1.8.0_201\jre\bin, org.jboss.logmanager.nocolor=true, sun.java.command=org.jboss.modules.Main -mp C:\wildfly16\modules org.jboss.as.standalone -b localhost --server-config=standalone.xml -Djboss.server.base.dir=C:\wildfly16\standalone, java.specification.vendor=Oracle Corporation, java.naming.factory.url.pkgs=org.jboss.as.naming.interfaces, java.home=C:\Program Files\Java\jdk1.8.0_201\jre, jboss.server.persist.config=true, file.separator=\, jboss.server.data.dir=C:\wildfly16\standalone\data, line.separator=
, java.vm.specification.vendor=Oracle Corporation, java.specification.name=Java Platform API Specification, jboss.server.base.dir=C:\wildfly16\standalone, hibernate.transaction.coordinator_class=class org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl, wicket.configuration=development, jboss.bind.address.management=localhost, sun.boot.class.path=C:\Program Files\Java\jdk1.8.0_201\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_201\jre\classes, hibernate.hbm2ddl.auto=update, user.script=, java.protocol.handler.pkgs=org.jboss.net.protocol|org.jboss.vfs.protocol, sun.management.compiler=HotSpot 64-Bit Tiered Compilers, java.runtime.version=1.8.0_201-b09, user.name=ptaszek, hibernate.enable_lazy_load_no_trans=true, file.encoding=Cp1250, sun.rmi.dgc.client.gcInterval=3600000, java.io.tmpdir=C:\Users\ptaszek\AppData\Local\Temp\, org.jboss.boot.log.file=C:\wildfly16\standalone\log\boot.log, jboss.modules.system.pkgs=org.jboss.byteman, java.version=1.8.0_201, java.vm.specification.name=Java Virtual Machine Specification, jboss.bind.address=localhost, java.awt.printerjob=sun.awt.windows.WPrinterJob, jboss.host.name=1501-10, org.jboss.security.context.ThreadLocal=true, sun.os.patch.level=, module.path=C:\wildfly16\modules, java.library.path=C:\Program Files\Java\jdk1.8.0_201\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;native;C:/Program Files/Java/jre1.8.0_211/bin/server;C:/Program Files/Java/jre1.8.0_211/bin;C:/Program Files/Java/jre1.8.0_211/lib/amd64;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Program Files\Microsoft MPI\Bin\;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\AOMEI Backupper;C:\Program Files\TortoiseSVN\bin;C:\Program Files (x86)\Microsoft SQL Server0\Tools\Binn\;C:\Program Files\Microsoft SQL Server0\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server0\DTS\Binn\;C:\Program Files\Microsoft SQL Server0\DTS\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC0\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC0\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server0\Tools\Binn\ManagementStudio\;C:\Program Files\MySQL\MySQL Shell 8.0\bin\;C:\eclipse;;., jboss.server.name=1501-10, java.vendor=Oracle Corporation, jboss.modules.dir=C:\wildfly16\modules, sun.io.unicode.encoding=UnicodeLittle, jboss.server.temp.dir=C:\wildfly16\standalone\tmp, sun.desktop=windows, file.encoding.pkg=sun.io, hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_HOLD, hibernate.dialect=org.hibernate.dialect.MySQL8Dialect, java.class.path=C:\wildfly16\jboss-modules.jar, jboss.server.deploy.dir=C:\wildfly16\standalone\data\content, java.vm.vendor=Oracle Corporation, user.variant=, user.timezone=Europe/Belgrade, os.name=Windows 10, java.vm.specification.version=1.8, program.name=JBossTools: WildFly 16 at localhost, hibernate.generate_statistics=false, sun.java.launcher=SUN_STANDARD, user.country=PL, hibernate.use_sql_comments=false, javax.persistence.sharedCache.mode=UNSPECIFIED, jboss.server.config.dir=C:\wildfly16\standalone\configuration, sun.cpu.endian=little, user.home=C:\Users\ptaszek, user.language=pl, jboss.qualified.host.name=1501-10, java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment, java.awt.headless=true, org.apache.xml.security.ignoreLineBreaks=true, sun.rmi.dgc.server.gcInterval=3600000, java.net.preferIPv4Stack=true, jboss.home.dir=C:\wildfly16, path.separator=;, os.version=10.0, java.endorsed.dirs=C:\Program Files\Java\jdk1.8.0_201\jre\lib\endorsed, java.runtime.name=Java(TM) SE Runtime Environment, hibernate.ejb.persistenceUnitName=default, sun.nio.ch.bugLevel=, java.vm.name=Java HotSpot(TM) 64-Bit Server VM, hibernate.show_sql=false, java.security.auth.login.config=jar:file:/C:/wildfly16/modules/system/layers/base/org/picketbox/main/picketbox-5.0.3.Final.jar!/auth.conf, jboss.server.log.dir=C:\wildfly16\standalone\log, java.vendor.url.bug=http://bugreport.sun.com/bugreport/, user.dir=C:\wildfly16\bin, os.arch=amd64, org.hibernate.envers.audit_strategy=org.hibernate.envers.strategy.ValidityAuditStrategy, javax.management.builder.initial=org.jboss.as.jmx.PluggableMBeanServerBuilder, hibernate.boot.CfgXmlAccessService.key=org.hibernate.boot.cfgxml.spi.LoadedConfig@35a3f1ae, java.util.logging.manager=org.jboss.logmanager.LogManager, java.vm.info=mixed mode, java.vm.version=25.201-b09, hibernate.bytecode.use_reflection_optimizer=false, hibernate.connection.datasource=HikariDataSource (HikariCpConnectionPool), java.ext.dirs=C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext, jboss.node.name=1501-10, java.class.version=52.0}
在我的 PersistenceJPAConfig 中:
@EnableJpaRepositories(basePackages = "pl.atmoterm", entityManagerFactoryRef = "localContainerEntityManagerFactoryBean")
@Bean
@DependsOn({"dataSource"})
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[]{
"pl.atmoterm.**.*"
});
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
em.setJpaProperties(additionalProperties());
return em;
}
使用 Spring Framework 5.1 和 Envers 设置 bean 注入确实没有太多涉及。侦听器实现不需要被 @Service
或 @Component
注释,因为这些 classes 实际上是由 Hibernate 构造的,然后 ManagedBeanRegistry
负责与任何 DI 框架协调习惯于 inject/wire 依赖关系。
如果您的 MyService
没有被注入到修订侦听器中,那么需要检查的内容很少:
- 确认您使用的是 Spring Framework 5.1 或更高版本。
虽然其他 spring 组件可能使用不同的版本方案,确保基础 Spring 框架版本确实是 5.1+ 很重要。
RevisionListener
配置正确吗?
我通常通过添加一个 @RevisionEntity
注释 class 和 @Entity
注释来配置它,然后指定@RevisionEntity
注释的值属性中的侦听器。如果您愿意,您应该能够使用 org.hibernate.envers.revision_listener
来指定监听器的完全限定 class 名称 class 否则。
- 你的
MyService
可以注入任何其他 spring bean 吗?
也许这里的问题是 Spring 根本没有构建你的 MyService
bean,这将导致依赖注入在修订侦听器的 bean 注入期间不提供实现。
我创建了一个小演示 here,您可以参考。我将考虑在本月晚些时候在 Hibernate 博客上发布一篇关于此的博客 post。
更新
简单地查看 Spring 框架源代码,我认为问题在于您手动创建了一个 LocalContainerEntityManagerFactoryBean
,当注入 bean 工厂时,它实际上并没有创建必要的发生依赖注入的 Hibernate 配置。
我认为您可能需要自己手动设置:
@Bean
@DependsOn({"dataSource"})
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean(ConfigurableListableBeanFactory beanFactory) {
// Create the LocalContainerEntityManagerBean like you were
// Pass beanFactory here so right configuration gets applied
em.setJpaProperties(additionalProperties(beanFactory));
return em;
}
private Properties additionalProperties(ConfigurableListableBeanFactory beanFactory) {
// add your properties here like you were before
Properties properties = new Properties();
// THIS HERE IS THE CRITICAL SETTING
properties.put(
"hibernate.resource.beans.container",
new SpringBeanContainer(beanFactory));
return properties
}
虽然 LocalContainerEntityManagerFactoryBean
是 BeanFactoryAware
,但它只是设置了一个内部 属性 而已。 属性 实际上并没有设置为 Hibernate 检测它的必要配置 属性,因此 Hibernate 最终默认为 CDI 注入,因为您处于 CDI 环境中。
在上面,在构建 EntityManagerFactory bean 时,我们在 BeanFactory 实例中进行了配置传递。我们将该工厂向下传递到 additionalProperties
,在那里我们手动将其应用到正确的 Hibernate 配置,然后传递到 Hibernate bootstrap。
如果使用Spring引导,最好使用ApplicationContextAware:
public class MyRevisionListener implements RevisionListener, ApplicationContextAware {
private MyService myService;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.myService = applicationContext.getBean(MyService.class);
}
@Override
public void newRevision(Object revisionEntity) {
MyRevisionEntity revinfo = (MyRevisionEntity) revisionEntity;
// Use myService here to set something on MyRevisionEntity
}
}
这是使用 Spring Boot 2.3.9 测试的。
有其他方法...您可以使用 spring 中的静态 class...
检查....
import org.hibernate.envers.RevisionListener;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
public class EnverRevisionListener implements RevisionListener{
@Override
public void newRevision(Object revisionEntity) {
EnverRevisionEntity revEntity = (EnverRevisionEntity) revisionEntity;
SecurityContext context = SecurityContextHolder.getContext();
Authentication auth = context.getAuthentication();
revEntity.setUserName(auth.getName());
}
}
我正在使用 Spring 5.1 和 Hibernate 5.3.9,包括 hibernate-envers。 我不知道如何将 spring bean 注入休眠环境自定义 RevisionListener。
我试过了
(@Service or @Component)
public class ExtendedRevisionListener implements RevisionListener {
@Autowired
private MyService myService;
void newRevision(Object revisionEntity){
myService.doSomething(...)
}
}
当然 class 包含在 @ComponentScan 包解析中。 一个问题是 myService 没有注入到监听器中。
在 hibernate-envers 文档中:
从 Hibernate Envers 5.3 开始,RevisionListener 现在支持依赖注入。 此功能取决于各种依赖框架,例如 CDI 和 Spring,以在 Hibernate ORM bootstrap 期间提供必要的实现以支持注入。如果没有提供符合条件的实现,将在没有注入的情况下构造 RevisionListener。
不幸的是,我还没有找到任何有效的例子。
@纳罗斯 我在 spring 持久性 JPA 中设置了 EntityMaganerFactoryBean 配置 -> entityManager = 新 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean()
10:49| DEBUG | SessionFactoryImpl.java 252 | Session factory constructed with filter configurations : {}
10:49| DEBUG | SessionFactoryImpl.java 253 | Instantiating session factory with properties: {hibernate.format_sql=true, awt.toolkit=sun.awt.windows.WToolkit, hibernate.id.new_generator_mappings=false, java.specification.version=1.8, logging.configuration=file:C:\wildfly16\standalone\configuration\logging.properties, sun.cpu.isalist=amd64, sun.jnu.encoding=Cp1250, sun.arch.data.model=64, org.jboss.resolver.warning=true, java.vendor.url=http://java.oracle.com/, javax.persistence.validation.mode=AUTO, sun.boot.library.path=C:\Program Files\Java\jdk1.8.0_201\jre\bin, org.jboss.logmanager.nocolor=true, sun.java.command=org.jboss.modules.Main -mp C:\wildfly16\modules org.jboss.as.standalone -b localhost --server-config=standalone.xml -Djboss.server.base.dir=C:\wildfly16\standalone, java.specification.vendor=Oracle Corporation, java.naming.factory.url.pkgs=org.jboss.as.naming.interfaces, java.home=C:\Program Files\Java\jdk1.8.0_201\jre, jboss.server.persist.config=true, file.separator=\, jboss.server.data.dir=C:\wildfly16\standalone\data, line.separator=
, java.vm.specification.vendor=Oracle Corporation, java.specification.name=Java Platform API Specification, jboss.server.base.dir=C:\wildfly16\standalone, hibernate.transaction.coordinator_class=class org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl, wicket.configuration=development, jboss.bind.address.management=localhost, sun.boot.class.path=C:\Program Files\Java\jdk1.8.0_201\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_201\jre\classes, hibernate.hbm2ddl.auto=update, user.script=, java.protocol.handler.pkgs=org.jboss.net.protocol|org.jboss.vfs.protocol, sun.management.compiler=HotSpot 64-Bit Tiered Compilers, java.runtime.version=1.8.0_201-b09, user.name=ptaszek, hibernate.enable_lazy_load_no_trans=true, file.encoding=Cp1250, sun.rmi.dgc.client.gcInterval=3600000, java.io.tmpdir=C:\Users\ptaszek\AppData\Local\Temp\, org.jboss.boot.log.file=C:\wildfly16\standalone\log\boot.log, jboss.modules.system.pkgs=org.jboss.byteman, java.version=1.8.0_201, java.vm.specification.name=Java Virtual Machine Specification, jboss.bind.address=localhost, java.awt.printerjob=sun.awt.windows.WPrinterJob, jboss.host.name=1501-10, org.jboss.security.context.ThreadLocal=true, sun.os.patch.level=, module.path=C:\wildfly16\modules, java.library.path=C:\Program Files\Java\jdk1.8.0_201\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;native;C:/Program Files/Java/jre1.8.0_211/bin/server;C:/Program Files/Java/jre1.8.0_211/bin;C:/Program Files/Java/jre1.8.0_211/lib/amd64;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Program Files\Microsoft MPI\Bin\;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\AOMEI Backupper;C:\Program Files\TortoiseSVN\bin;C:\Program Files (x86)\Microsoft SQL Server0\Tools\Binn\;C:\Program Files\Microsoft SQL Server0\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server0\DTS\Binn\;C:\Program Files\Microsoft SQL Server0\DTS\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC0\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC0\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server0\Tools\Binn\ManagementStudio\;C:\Program Files\MySQL\MySQL Shell 8.0\bin\;C:\eclipse;;., jboss.server.name=1501-10, java.vendor=Oracle Corporation, jboss.modules.dir=C:\wildfly16\modules, sun.io.unicode.encoding=UnicodeLittle, jboss.server.temp.dir=C:\wildfly16\standalone\tmp, sun.desktop=windows, file.encoding.pkg=sun.io, hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_HOLD, hibernate.dialect=org.hibernate.dialect.MySQL8Dialect, java.class.path=C:\wildfly16\jboss-modules.jar, jboss.server.deploy.dir=C:\wildfly16\standalone\data\content, java.vm.vendor=Oracle Corporation, user.variant=, user.timezone=Europe/Belgrade, os.name=Windows 10, java.vm.specification.version=1.8, program.name=JBossTools: WildFly 16 at localhost, hibernate.generate_statistics=false, sun.java.launcher=SUN_STANDARD, user.country=PL, hibernate.use_sql_comments=false, javax.persistence.sharedCache.mode=UNSPECIFIED, jboss.server.config.dir=C:\wildfly16\standalone\configuration, sun.cpu.endian=little, user.home=C:\Users\ptaszek, user.language=pl, jboss.qualified.host.name=1501-10, java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment, java.awt.headless=true, org.apache.xml.security.ignoreLineBreaks=true, sun.rmi.dgc.server.gcInterval=3600000, java.net.preferIPv4Stack=true, jboss.home.dir=C:\wildfly16, path.separator=;, os.version=10.0, java.endorsed.dirs=C:\Program Files\Java\jdk1.8.0_201\jre\lib\endorsed, java.runtime.name=Java(TM) SE Runtime Environment, hibernate.ejb.persistenceUnitName=default, sun.nio.ch.bugLevel=, java.vm.name=Java HotSpot(TM) 64-Bit Server VM, hibernate.show_sql=false, java.security.auth.login.config=jar:file:/C:/wildfly16/modules/system/layers/base/org/picketbox/main/picketbox-5.0.3.Final.jar!/auth.conf, jboss.server.log.dir=C:\wildfly16\standalone\log, java.vendor.url.bug=http://bugreport.sun.com/bugreport/, user.dir=C:\wildfly16\bin, os.arch=amd64, org.hibernate.envers.audit_strategy=org.hibernate.envers.strategy.ValidityAuditStrategy, javax.management.builder.initial=org.jboss.as.jmx.PluggableMBeanServerBuilder, hibernate.boot.CfgXmlAccessService.key=org.hibernate.boot.cfgxml.spi.LoadedConfig@35a3f1ae, java.util.logging.manager=org.jboss.logmanager.LogManager, java.vm.info=mixed mode, java.vm.version=25.201-b09, hibernate.bytecode.use_reflection_optimizer=false, hibernate.connection.datasource=HikariDataSource (HikariCpConnectionPool), java.ext.dirs=C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext, jboss.node.name=1501-10, java.class.version=52.0}
在我的 PersistenceJPAConfig 中:
@EnableJpaRepositories(basePackages = "pl.atmoterm", entityManagerFactoryRef = "localContainerEntityManagerFactoryBean")
@Bean
@DependsOn({"dataSource"})
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[]{
"pl.atmoterm.**.*"
});
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
em.setJpaProperties(additionalProperties());
return em;
}
使用 Spring Framework 5.1 和 Envers 设置 bean 注入确实没有太多涉及。侦听器实现不需要被 @Service
或 @Component
注释,因为这些 classes 实际上是由 Hibernate 构造的,然后 ManagedBeanRegistry
负责与任何 DI 框架协调习惯于 inject/wire 依赖关系。
如果您的 MyService
没有被注入到修订侦听器中,那么需要检查的内容很少:
- 确认您使用的是 Spring Framework 5.1 或更高版本。
虽然其他 spring 组件可能使用不同的版本方案,确保基础 Spring 框架版本确实是 5.1+ 很重要。 RevisionListener
配置正确吗?
我通常通过添加一个@RevisionEntity
注释 class 和@Entity
注释来配置它,然后指定@RevisionEntity
注释的值属性中的侦听器。如果您愿意,您应该能够使用org.hibernate.envers.revision_listener
来指定监听器的完全限定 class 名称 class 否则。- 你的
MyService
可以注入任何其他 spring bean 吗?
也许这里的问题是 Spring 根本没有构建你的MyService
bean,这将导致依赖注入在修订侦听器的 bean 注入期间不提供实现。
我创建了一个小演示 here,您可以参考。我将考虑在本月晚些时候在 Hibernate 博客上发布一篇关于此的博客 post。
更新
简单地查看 Spring 框架源代码,我认为问题在于您手动创建了一个 LocalContainerEntityManagerFactoryBean
,当注入 bean 工厂时,它实际上并没有创建必要的发生依赖注入的 Hibernate 配置。
我认为您可能需要自己手动设置:
@Bean
@DependsOn({"dataSource"})
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean(ConfigurableListableBeanFactory beanFactory) {
// Create the LocalContainerEntityManagerBean like you were
// Pass beanFactory here so right configuration gets applied
em.setJpaProperties(additionalProperties(beanFactory));
return em;
}
private Properties additionalProperties(ConfigurableListableBeanFactory beanFactory) {
// add your properties here like you were before
Properties properties = new Properties();
// THIS HERE IS THE CRITICAL SETTING
properties.put(
"hibernate.resource.beans.container",
new SpringBeanContainer(beanFactory));
return properties
}
虽然 LocalContainerEntityManagerFactoryBean
是 BeanFactoryAware
,但它只是设置了一个内部 属性 而已。 属性 实际上并没有设置为 Hibernate 检测它的必要配置 属性,因此 Hibernate 最终默认为 CDI 注入,因为您处于 CDI 环境中。
在上面,在构建 EntityManagerFactory bean 时,我们在 BeanFactory 实例中进行了配置传递。我们将该工厂向下传递到 additionalProperties
,在那里我们手动将其应用到正确的 Hibernate 配置,然后传递到 Hibernate bootstrap。
如果使用Spring引导,最好使用ApplicationContextAware:
public class MyRevisionListener implements RevisionListener, ApplicationContextAware {
private MyService myService;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.myService = applicationContext.getBean(MyService.class);
}
@Override
public void newRevision(Object revisionEntity) {
MyRevisionEntity revinfo = (MyRevisionEntity) revisionEntity;
// Use myService here to set something on MyRevisionEntity
}
}
这是使用 Spring Boot 2.3.9 测试的。
有其他方法...您可以使用 spring 中的静态 class...
检查....
import org.hibernate.envers.RevisionListener;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
public class EnverRevisionListener implements RevisionListener{
@Override
public void newRevision(Object revisionEntity) {
EnverRevisionEntity revEntity = (EnverRevisionEntity) revisionEntity;
SecurityContext context = SecurityContextHolder.getContext();
Authentication auth = context.getAuthentication();
revEntity.setUserName(auth.getName());
}
}