Spring + Hiberante

0

Cześć, jestem początkujący użytkownikiem springa i hibernate'a i proszę o poradę, gdyż nie mogę znaleźć rozwiązania.
Najpierw przedstawię kod, a potem pytanie.

HibernateConfig.java

@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());
  }

  @Bean
  public HibernateTemplate hibernateTemplate() {
    return new HibernateTemplate(sessionFactory());
  }

}

Person.java

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

  @Id
  @Column(name = "id")
  private int id;
  @Column(name = "name")
  private String 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

@Repository
public class PersonDao {

  @Autowired
  private HibernateTemplate hibernateTemplate;


  public void savePerson(){
    Person person = new Person();
    person.setId(2);
    person.setName("NazwaTest");
    hibernateTemplate.save(person);
  }

}

PersonService.java

@Service
@Transactional
public class PersonService {

  private PersonDao personDao = new PersonDao();

  public void addNewPerson(){
    personDao.savePerson();
  }
}

PersonController.java

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

Kod generalnie bardzo prosty, bo na razie uczę się właśnie schematów i działania.
Problem w tym, że gdy uruchomię aplikację i wejdę na stronę wyrzuca mi błąd java.lang.NullPointerException: null
Generalnie dotoczy to pliku PersonDao.java oraz linii hibernateTemplate.save(person);
Wyczytałem, że to chyba błąd z niewłaściwie zadeklarowanymi beanami i autowire, ale nie mogę sobie z tym poradzić. Czy ktoś mógłby dać jakąś wskazówkę?

1

Jak już zdajesz się na Springa, to nie twórz beanów poprzez new, tylko autowiruj. Czyli zamiast

private PersonDao personDao = new PersonDao();

będzie

@Autowired
PersonDao personDao

A już w ogóle najlepiej jakbyś wstrzykiwał te zależności poprzez konstruktor, czyli

@Autowired
public PersonService(PersonDao personDao) {
   this.personDao = personDao;
}

A jak korzystasz ze Springa wyższego lub równego 4.3, to możesz nawet pominąć adnotację i będzie ostatecznie:

public PersonService(PersonDao personDao) {
   this.personDao = personDao;
}

analogicznie później dla serwisu.

1

Dobrze wyczytałeś. Zamiast new PersonDao(); dodaj adnotację @Autowired. Tak samo w kontrolerze do serwisu. Po to masz Springa, a raczej jego kontener IoC (nie wiem poczytaj o IoC, dependency injection, bo nie zrozumiałeś chyba czegoś), żebyś nie tworzył obiektów. Inaczej oddajesz Springowi kontrole nad tworzeniem obiektów to są podstawy zobacz sobie Artur Owczarek na yt.

0

Okej, dokonałem pewnych modyfikacji. Wygląda to teraz tak:

PersonDao.java

@Repository
public class PersonDao implements IPersonDao {

  @Autowired
  private HibernateTemplate hibernateTemplate;

  public PersonDao(){}

  public void savePerson(){
    Person person = new Person();
    person.setId(2);
    person.setName("NazwaTest");
    hibernateTemplate.save(person);
  }

}

PersonService.java

@Service
public class PersonService{

  @Autowired
  PersonDao personDao;

  public  PersonService(){}

  public void addNewPerson(){
    personDao.savePerson();
  }
}

PersonController.java


@Controller
public class PersonController {

  @Autowired
  PersonService personService;

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

Niestety, teraz program nie chce się uruchomić. Problem jest z plikiem PersonService.java a konkretnie:

  @Autowired
  PersonDao personDao;

Gdyż nie może dokonać autowire, bo taki bean nie może zostać odnaleziony, ale przez adnotację @Repository i konstruktor bezparametrowy powinno zadziałać.

Co może być nie tak?

Dodatkowo załączam Initializer, który może ma jakiś błąd, dlatego jest problem.
MyWebInitializer.java

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[] { "/" };
  }

}

SpringWebConfig.java

@EnableWebMvc //<mvc:annotation-driven />
@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;
  }

}

SpringRootConfig.java

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

}

HibertnateConfig.java

@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());
  }

  @Bean
  public HibernateTemplate hibernateTemplate() {
    return new HibernateTemplate(sessionFactory());
  }
}
0

@Warmix: Masz ustawione component scan w package (po pl pakiet? już mi nazwy uciekają) gdzie jest PersonDao.java? Ten HibernateTemplate skąd wziąłeś? To nie jest czasem przestarzałe? Poczytaj o SessionFactory w dokumentacji Springa.

Korzystasz z mavena czy gradla?

EDIT: https://stackoverflow.com/a/43801315

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