如何在Hibernate BeforeExecutionGenerator中注入Bean(Quarkus环境)
在Quarkus中为Hibernate BeforeExecutionGenerator注入Bean或配置属性
问题原因
Hibernate的BeforeExecutionGenerator实例由Hibernate自身负责实例化,并不受CDI容器管理,因此直接使用@Inject注解或标记@ApplicationScoped都无法触发CDI的注入逻辑。
解决方案
1. 手动获取CDI Bean实例
在Quarkus中,可以通过Arc.container()手动获取CDI管理的Bean实例,这是Quarkus原生推荐的方式:
修改MyIdGenerator类如下:
import io.quarkus.arc.Arc; import io.quarkus.arc.Instance; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.id.BeforeExecutionGenerator; import org.hibernate.id.enhanced.EventType; import java.util.EnumSet; public class MyIdGenerator implements BeforeExecutionGenerator { @Override public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) { // 获取OtherService的CDI实例 Instance<OtherService> serviceInstance = Arc.container().instance(OtherService.class); OtherService service = serviceInstance.get(); return service.nextId(); } @Override public EnumSet<EventType> getEventTypes() { return INSERT_ONLY; } }
2. 注入配置属性
如果需要读取配置属性,可以使用Quarkus的ConfigProvider直接获取:
import io.quarkus.arc.Arc; import io.quarkus.arc.Instance; import io.smallrye.config.ConfigProvider; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.id.BeforeExecutionGenerator; import org.hibernate.id.enhanced.EventType; import java.util.EnumSet; public class MyIdGenerator implements BeforeExecutionGenerator { private final String customConfig; public MyIdGenerator() { // 从配置文件读取属性,比如application.properties中的my.id.generator.prefix this.customConfig = ConfigProvider.getConfig().getValue("my.id.generator.prefix", String.class); } @Override public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) { Instance<OtherService> serviceInstance = Arc.container().instance(OtherService.class); OtherService service = serviceInstance.get(); // 结合配置属性生成ID return service.nextIdWithPrefix(customConfig); } @Override public EnumSet<EventType> getEventTypes() { return INSERT_ONLY; } }
注意事项
- 不要在生成器的构造方法中获取CDI Bean,因为此时CDI容器可能尚未完全初始化,应在
generate方法中执行获取操作。 - 确保被获取的Bean(如
OtherService)已被CDI正确管理(比如标记了@ApplicationScoped、@Singleton等作用域注解)。
内容的提问来源于stack exchange,提问作者Andrei Yusupau
相关产品推荐
相关产品推荐

