为啥我在 Spring-boot 应用程序中通过 SessionFactory 有循环依赖?
Posted
技术标签:
【中文标题】为啥我在 Spring-boot 应用程序中通过 SessionFactory 有循环依赖?【英文标题】:Why do I have a circular dependency through SessionFactory in Spring-boot application?为什么我在 Spring-boot 应用程序中通过 SessionFactory 有循环依赖? 【发布时间】:2020-02-02 00:52:48 【问题描述】:我在启动 Spring-Boot 应用程序时遇到了错误。
现在,我想在 DAO 存储库中使用 HibernateDaoSupport
,因为 Spring boot 不会自动创建 SessionFactory
。所以,我从 EntityManagerFactory 创建了SessionFactory
bean,并尝试在 DAO 类中自动装配它。
但我收到以下错误:
Description:
The dependencies of some of the beans in the application context form a cycle:
fooDao defined in file [/home/user/test/out/production/classes/by/test/testing_the_java_service_layer/repository/FooDao.class]
┌─────┐
| sessionFactory defined in class path resource [by/test/testing_the_java_service_layer/configuration/Config.class]
└─────┘
我不明白为什么SessionFactory
指的是FooDao
类。
以下是代码示例:
FooDao.java
@Repository
public class FooDao extends HibernateDaoSupport
@Autowired
public void setSessionFactories( SessionFactory sessionFactory )
setSessionFactory( sessionFactory );
@Transactional
public int create( Foo entity )
return (int) this.getHibernateTemplate().save( entity );
Config.java
@ComponentScan( basePackages = "by.test" )
@Configuration
public class Config
/*
* Spring boot doesn't create SessionFactory bean, so we have to create it manually, using EntityManagerFactory
*/
@Bean
public SessionFactory sessionFactory( EntityManagerFactory entityManagerFactory )
return entityManagerFactory.unwrap( SessionFactory.class );
Foo.java
@Entity
@Table( name = "bibis" )
public class Foo
@Id
@Column( name = "foo", nullable = false )
public int foo;
@Column( name = "bar" )
public String bar;
TestApplication.java
@SpringBootApplication
public class TestApplication
public static void main( String[] args )
SpringApplication.run( TestApplication.class, args );
application.yaml
spring:
datasource:
username: 'bibis'
password: 'bibis'
schema: 'bibis'
host: 'localhost:3306'
url: 'jdbc:mariadb://localhost:3306/bibis'
以及来自 build.gradle 的 gradle 依赖项
implementation('org.mariadb.jdbc:mariadb-java-client')
developmentOnly 'org.springframework.boot:spring-boot-devtools'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.1.8.RELEASE'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
我尝试使用@Lazy 注释、构造函数或字段注入,但没有帮助。
【问题讨论】:
【参考方案1】:嗯,你要明确你是要使用JPA还是Hibernate(JPA的实现),EntityManager对应JPA,SessionFactory对应Hibernate,如果使用EntityManager就不需要使用SessionFactory, EM 在后台调用休眠会话。而如果你需要一些EntityManager中没有的特定功能,可以通过调用来获取会话:
Session session = entityManager.unwrap(Session.class);
重构并尝试
【讨论】:
感谢您的回答,但我不需要 Session 对象,我只想使用需要 SessionFactory 的 HibernateTemplate。它不是生产代码,仅用于培训目的。【参考方案2】:我已经参考了Spring Boot - Handle to Hibernate SessionFactory的答案
从Config
类返回HibernateJpaSessionFactoryBean
obj 而不是SessionFactory
对象。
修改后的代码为:
@ComponentScan( basePackages = "by.test" )
@Configuration
public class Config
@Bean
public HibernateJpaSessionFactoryBean sessionFactory(EntityManagerFactory entityManagerFactory)
HibernateJpaSessionFactoryBean hibernateJpaSessionFactoryBean = new HibernateJpaSessionFactoryBean();
hibernateJpaSessionFactoryBean.setEntityManagerFactory(entityManagerFactory);
return hibernateJpaSessionFactoryBean;
或者你可以这样做:
@Repository
public class FooDao extends HibernateDaoSupport
@Autowired
public void setSessionFactories(EntityManagerFactory entityManagerFactory)
setSessionFactory(entityManagerFactory.unwrap(SessionFactory.class));
@Transactional
public int create(Foo entity)
return (int) this.getHibernateTemplate().save( entity );
【讨论】:
第一个变体对我没有帮助。第二种变体是可以的。谢谢!但我还是不明白,为什么我有循环依赖。 SessionFactory 在哪里引用了我的 FooDao?【参考方案3】:在我看来,当您在 setter 值中使用 @Autowired 时,它会创建循环依赖项。这是一种更好的方法,可以解决您作为属性构造函数的问题
@Repository
public class FooDao extends HibernateDaoSupport
@Autowired
public FooDao(SessionFactory sessionFactory)
this.sessionFactory = sessionFactory
@Transactional
public int create( Foo entity )
return (int) this.getHibernateTemplate().save( entity );
【讨论】:
不幸的是它没有帮助。看起来它不依赖于构造函数或字段注入。以上是关于为啥我在 Spring-boot 应用程序中通过 SessionFactory 有循环依赖?的主要内容,如果未能解决你的问题,请参考以下文章
Django:为啥当我在 django 中通过 popen 使用 Ghostscript 时会出现“找不到文件”错误
在 Symbian^3 中通过 VBO 方法加载 3D 对象时获取 KERN-EXEC 3,为啥?