Spring + gradle + hibernate - błąd z autowired

0

Struktura aplikacji:
title

Person.java

package com.test.business;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "person")
public class Person {

  @Id
  @Column(name = "id")
  private int id;
  @Column(name = "name")
  private String name;

  public Person() {
  }

  public Person(int id, String name) {
    this.id = id;
    this.name = name;
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}

PersonDao.java

package com.test.dao;

import com.test.business.Person;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PersonDao extends CrudRepository<Person, Long> {

}

PersonService.java

package com.test.service;

import com.test.business.Person;
import com.test.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PersonService{

  @Autowired
  private PersonDao personDao;

  public Person addNewPerson(){
    return personDao.save(new Person(2, "Test2"));
  }
}

PersonController.java

package com.test.controller;


import com.test.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class PersonController {

  @Autowired
  private PersonService personService;

  @GetMapping(value="/")
  @ResponseBody
  public String printWelcome() {
    personService.addNewPerson();
    return "home";
  }
}

MyWebInitializer.java

package com.test;

import com.test.config.SpringRootConfig;
import com.test.config.SpringWebConfig;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MyWebInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer {

  @Override
  protected Class<?>[] getRootConfigClasses() {
    return new Class[] { SpringRootConfig.class };
  }

  @Override
  protected Class<?>[] getServletConfigClasses() {
    return new Class[] { SpringWebConfig.class };
  }

  @Override
  protected String[] getServletMappings() {
    return new String[] { "/" };
  }

}

SpringRootConfig.java

package com.test.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({"com.test.service", "com.test.dao"})
public class SpringRootConfig {

}

SpringWebConfig.java

package com.test.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@EnableWebMvc
@Configuration
@ComponentScan({ "com.test.controller" })
public class SpringWebConfig implements WebMvcConfigurer {

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**")
        .addResourceLocations("/resources/");
  }

  @Bean
  public InternalResourceViewResolver viewResolver() {
    InternalResourceViewResolver viewResolver
        = new InternalResourceViewResolver();
    viewResolver.setViewClass(JstlView.class);
    viewResolver.setPrefix("/WEB-INF/views/jsp/");
    viewResolver.setSuffix(".jsp");
    return viewResolver;
  }

}

HibernateConfig.java

package com.test.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBuilder;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.test.config"})
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfig {

  @Autowired
  private Environment environment;

  @Bean
  public SessionFactory sessionFactory() {
    LocalSessionFactoryBuilder builder =
        new LocalSessionFactoryBuilder(dataSource());
    builder.scanPackages("com.test.business")
        .addProperties(hibernateProperties());

    return builder.buildSessionFactory();
  }

  private Properties hibernateProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
    properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
    return properties;
  }

  @Bean
  public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
    dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
    dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
    dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
    return dataSource;
  }

  @Bean
  public HibernateTransactionManager txManager() {
    return new HibernateTransactionManager(sessionFactory());
  }

}

Podczas budowy programu nie ma żadnych błędów, natomiast podczas uruchamiania wyrzuca błąd:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'personService': Unsatisfied dependency expressed through field 'personDao'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.test.dao.PersonDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

(....)

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.test.dao.PersonDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Proszę o jakieś wskazówki, dlaczego nie może stworzyć mit ego beana personService, które właściwie spowodowane jest brakiem beana PersonDao, choć ta klasa posiada adnotację @Repository, do tego jest obejmowana przez @ComponentScan.

0

Też to dzisiaj miałem. Intellij 2018.2 podkreślał mi SessionFactory w klasie DAO. Jak usunąłem adnotację @Autowired, nie ma błędu. Tylko, że nie mogę korzystać z Hibernate, nie wiem dlaczego może dlatego, że mam wersję EAP.

Może to ma jakiś związek z tym, że w Spring 5 nie trzeba już stosować adnotacji @Autowired tylko spring sam o to zadba. Nie wiem, bo nie testowałem jeszcze zapisu do bazy z SessionFactory.

4

Na 1 rzut oka to Ty mieszasz używanie Hibernate bezpośrednio ze Springiem Data JPA.
Albo konfiguruj pod Spring Data JPA (musisz walnąc też adnotacje @EnableJpaReposistory czy jakoś tak) albo pod Hibernate bezpośrednio
Repository na Intefersjach tez nie działa, komponenty są na implementacjach...

0

Pokaż jeszcze xml z zależnościami.

0

Wprowadziłem w błąd. Moja wina, nie ustawiłem datasource w aplikacji i się dziwiłem czemu nie działa

https://docs.spring.io/spring/docs/4.3.18.RELEASE/spring-framework-reference/htmlsingle/#orm-session-factory-setup

1 użytkowników online, w tym zalogowanych: 0, gości: 1