Почему у меня есть циклическая зависимость через SessionFactory в приложении Spring-boot? - PullRequest
2 голосов
/ 03 октября 2019

Я столкнулся с ошибкой при запуске приложения Spring-Boot.

Теперь я хочу использовать HibernateDaoSupport в репозитории DAO, так как Spring boot не создает SessionFactory автоматически. Итак, я создал SessionFactory bean-компонент из EntityManagerFactory и попытался автоматически связать его в классе 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]
└─────┘

Iне понимаю, почему 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'

и зависимости gradle от build.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, конструктор илиполевая инъекция, но это не помогло.

Ответы [ 3 ]

1 голос
/ 03 октября 2019

Я передал ответ от Spring Boot - дескриптор Hibernate SessionFactory

Возврат HibernateJpaSessionFactoryBean obj вместо SessionFactory объекта из Config класса.

Модифицированный код будет:

@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 );
    }
}
0 голосов
/ 03 октября 2019

Что ж, вы должны уточнить, собираетесь ли вы использовать JPA или Hibernate (реализация JPA), EntityManager соответствует JPA, а SessionFactory - Hibernate. Если вы не используете EntityManager, не нужно использовать SessionFactory, EM вызывает сеанс гибернации подкапот. И если вам нужны некоторые специфические функции, которые недоступны в EntityManager, вы можете получить сеанс, позвонив по номеру:

Session session = entityManager.unwrap(Session.class);

, измените рефакторинг и попробуйте

0 голосов
/ 03 октября 2019

Мне кажется, что когда вы используете @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 );
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...