简体   繁体   中英

Could not autowire hibernate 5 sessionfactory with spring 5

I'm trying to autowire hibernate 5 session factory bean with spring 5 in my DAO class. Maybe someone can see my mistakes here? Tried using Hibernate 4, EntityManagerFactory but every time it's hopeless. Configuration class:

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.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"webApp"})
@EnableTransactionManagement
@PropertySource("classpath:props.dbProps.properties")
public class WebConfig implements WebMvcConfigurer {

private static final String DRIVER = "driver";
private static final String URL = "url";
private static final String USER_NAME = "name";
private static final String PASSWORD = "pass";
private static final String SCAN = "packages";
private static final String DIALECT = "dialect";
private static final String SHOW_SQL = "showSql";
private static final String HBM2DLL = "hbm2dll";

@Resource
private Environment env;

@Bean
public ViewResolver viewResolver(SpringTemplateEngine engine){
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(engine);
    return resolver;
}

@Bean
public SpringTemplateEngine templateEngine(SpringResourceTemplateResolver templateResolver){
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setTemplateResolver(templateResolver);
    return engine;
}

@Bean
public SpringResourceTemplateResolver templateResolver(){
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setPrefix("classpath:/templates/");
    resolver.setSuffix(".html");
    resolver.setTemplateMode(TemplateMode.HTML);
    return resolver;
}

@Bean
public MultipartResolver multipartResolver(){
    return new StandardServletMultipartResolver();
}

@Bean
public DataSource dataSource(){
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getRequiredProperty(DRIVER));
    dataSource.setUrl(env.getRequiredProperty(URL));
    dataSource.setUsername(env.getRequiredProperty(USER_NAME));
    dataSource.setPassword(env.getRequiredProperty(PASSWORD));
    return dataSource;
}

@Bean
public LocalSessionFactoryBean getSessionFactory(){
    final LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean();
    lsfb.setDataSource(dataSource());
    lsfb.setPackagesToScan(env.getRequiredProperty(SCAN));
    lsfb.setHibernateProperties(hibProps());
    return lsfb;
}

@Bean
public PlatformTransactionManager transactionManager(){
    HibernateTransactionManager tx = new HibernateTransactionManager();
    tx.setSessionFactory(getSessionFactory().getObject());
    return tx;
}

private Properties hibProps(){
    Properties p = new Properties();
    p.put(DIALECT, env.getRequiredProperty(DIALECT));
    p.put(SHOW_SQL, env.getRequiredProperty(SHOW_SQL));
    p.put(HBM2DLL, env.getRequiredProperty(HBM2DLL));
    return p;
}

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if(!registry.hasMappingForPattern("/static/**")){
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/");
    }
}
}

Tried to autowire through constructor and setter - nothing helps. DAO Class:

package webApp.data;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import webApp.model.Human;

import java.util.List;

@org.springframework.stereotype.Repository
public class HumanRepositoryImpl implements Repository<Human> {

    @Autowired
    private SessionFactory sessionFactory;

    private Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override
    public Human get(long id) {
        Human result = (Human)getSession().get(Human.class, id);
        return result;
    }

    @Override
    public Human getByName(String name) {
        Human result = (Human) getSession().createQuery("from human where name = '" + name + "'");
        return result;
    }

    @Override
    public void set(Human value) {
        getSession().save(value);
    }

    @Override
    public void update(Human value) {
        Human forUpdate = get(value.getId());
        forUpdate.setFirstName(value.getFirstName());
        forUpdate.setLastName(value.getLastName());
        forUpdate.setUsername(value.getUsername());
        forUpdate.setEmail(value.getEmail());
        forUpdate.setPassword(value.getPassword());
        getSession().update(forUpdate);
    }

    @Override
    public void delete(Human value) {
        Human forDelete = get(value.getId());
        if(forDelete != null)
            getSession().delete(forDelete);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Human> list() {
        return getSession().createQuery("from human").list();
    }
}

Dependencies: Spring 5.0.2.Release, Hibernate 5.2.12.Final

Exception Stack Trace:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'humanRepositoryImpl': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.hibernate.SessionFactory' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1344)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:758)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:409)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:291)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
    at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:890)
    at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:532)
    at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:853)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:344)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1514)
    at org.eclipse.jetty.maven.plugin.JettyWebAppContext.startWebapp(JettyWebAppContext.java:359)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1476)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:785)
    at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:261)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:545)
    at org.eclipse.jetty.maven.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:434)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:113)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:167)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:113)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
    at org.eclipse.jetty.server.Server.start(Server.java:449)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
    at org.eclipse.jetty.server.Server.doStart(Server.java:416)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.maven.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:467)
    at org.eclipse.jetty.maven.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:333)
    at org.eclipse.jetty.maven.plugin.JettyRunMojo.execute(JettyRunMojo.java:180)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
    at org.codehaus.classworlds.Launcher.main(Launcher.java:47)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.hibernate.SessionFactory' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1504)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1101)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:583)
    ... 68 more

Do you add sessionfactory in database.xml file like this:

  <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
            <property name="dataSource" ref="dataSource"/>
            <property name="packagesToScan">
                <list>
                    <value>com.isgm.iis.model</value> <!-- replace with your package name -->
                </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                    <prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop>
                    <prop key="hibernate.format_sql">${hibernate.format_sql:false}</prop>
                </props>
            </property>       
        </bean>

I don't think its a good design to mix up @EnableWebMvc with @EnableTransactionManagement. You should clear a separate class for Hibernate configuration in same package of class WebConfig. Remove the below code.

@EnableTransactionManagement
@PropertySource("classpath:props.dbProps.properties")

@Bean
public DataSource dataSource(){
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getRequiredProperty(DRIVER));
    dataSource.setUrl(env.getRequiredProperty(URL));
    dataSource.setUsername(env.getRequiredProperty(USER_NAME));
    dataSource.setPassword(env.getRequiredProperty(PASSWORD));
    return dataSource;
}

@Bean
public LocalSessionFactoryBean getSessionFactory(){
    final LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean();
    lsfb.setDataSource(dataSource());
    lsfb.setPackagesToScan(env.getRequiredProperty(SCAN));
    lsfb.setHibernateProperties(hibProps());
    return lsfb;
}

@Bean
public PlatformTransactionManager transactionManager(){
    HibernateTransactionManager tx = new HibernateTransactionManager();
    tx.setSessionFactory(getSessionFactory().getObject());
    return tx;
}

private Properties hibProps(){
    Properties p = new Properties();
    p.put(DIALECT, env.getRequiredProperty(DIALECT));
    p.put(SHOW_SQL, env.getRequiredProperty(SHOW_SQL));
    p.put(HBM2DLL, env.getRequiredProperty(HBM2DLL));
    return p;
}

Clear a separate class like below. I have written code for Hibernate xml config, you could also config properties file. Also, you haven't mentioned any class in setAnnotatedClasses method of LocalSessionFactoryBean, add those. This configuration is recommended for Spring 5 with Hibernate 5.

@Configuration
@EnableTransactionManagement
public class HibernateConfig {

    @Autowired
    private ApplicationContext context;

    @Bean
    public LocalSessionFactoryBean getSessionFactory() {
        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
        factoryBean.setConfigLocation(context.getResource("classpath:hibernate.cfg.xml"));
        factoryBean.setAnnotatedClasses(User.class);
        return factoryBean;
    }

    @Bean
    public HibernateTransactionManager getTransactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(getSessionFactory().getObject());
        return transactionManager;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM