Spring Boot 2.0.x中@Configuration类注入EntityManagerFactory报空指针问题
我原本在Spring Boot 1.5.x中使用以下代码,通过JPA EntityManagerFactory获取Hibernate SessionFactory,用来查询MySQL数据:
@Configuration public class DatabaseConfig { @Autowired private EntityManagerFactory entityManagerFactory; @Bean public SessionFactory getSessionFactory() { if (entityManagerFactory.unwrap(SessionFactory.class) == null) { throw new NullPointerException("Factory is not a hibernate factory"); } return entityManagerFactory.unwrap(SessionFactory.class); } }
升级到Spring Boot 2.0.1版本后,出现了如下错误:
Error creating bean with name 'databaseConfig': Unsatisfied dependency expressed through field 'entityManagerFactory';
请问如何在Spring Boot 2.0.x中解决此问题?
这个问题是因为Spring Boot 2.x在JPA bean的管理逻辑上做了调整,原来直接可注入的EntityManagerFactory现在不再是顶级可注入bean,而是由LocalContainerEntityManagerFactoryBean托管,所以直接注入会找不到对应的bean实例。我给你几个实用的解决办法:
方案一:通过EntityManager间接获取SessionFactory
这是最稳妥的方式,利用@PersistenceContext注入EntityManager,再从中解包获取Session和SessionFactory:
@Configuration public class DatabaseConfig { @PersistenceContext private EntityManager entityManager; @Bean public SessionFactory getSessionFactory() { Session session = entityManager.unwrap(Session.class); SessionFactory sessionFactory = session.getSessionFactory(); if (sessionFactory == null) { throw new NullPointerException("Factory is not a hibernate factory"); } return sessionFactory; } }
方案二:直接注入LocalContainerEntityManagerFactoryBean
如果你还是想直接操作EntityManagerFactory的源头bean,可以注入LocalContainerEntityManagerFactoryBean,然后调用它的getObject()方法获取实际的EntityManagerFactory实例:
@Configuration public class DatabaseConfig { @Autowired private LocalContainerEntityManagerFactoryBean entityManagerFactoryBean; @Bean public SessionFactory getSessionFactory() { EntityManagerFactory entityManagerFactory = entityManagerFactoryBean.getObject(); if (entityManagerFactory.unwrap(SessionFactory.class) == null) { throw new NullPointerException("Factory is not a hibernate factory"); } return entityManagerFactory.unwrap(SessionFactory.class); } }
方案三:简化配置,直接使用自动注册的SessionFactory
其实Spring Boot 2.x已经会自动帮你注册SessionFactory bean了,你完全可以省去自定义的DatabaseConfig类,直接在需要使用的地方注入SessionFactory即可:
// 在需要的Service/Repository中直接注入 @Autowired private SessionFactory sessionFactory;
这样就能完美适配Spring Boot 2.x的环境,解决依赖注入的问题啦。
内容的提问来源于stack exchange,提问作者trimaximus

