从 Migrate 迁移到 Spring MVC 4 + Hibernate5

Posted

技术标签:

【中文标题】从 Migrate 迁移到 Spring MVC 4 + Hibernate5【英文标题】:Migrating from Migrate to Spring MVC 4 + Hibernate5 【发布时间】:2017-08-03 22:39:51 【问题描述】:

我正在将应用程序从 Jersey 1.18、Spring 3、Hibernate 3.6、Maven 迁移到全新的架构:Spring 4.3(通过 Spring Boot)、Hibernate 5Gradle

在将 Spring application.xml“移植”到 Code-Base 配置期间,我遇到了以下异常:

创建名为“jpaContext”的 bean 时出错:依赖项不满足 ... 没有找到符合条件的 bean 依赖项 [java.util.Set]

这里是长堆栈跟踪

2017-03-13 19:44:42.814  WARN 40010 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jpaContext': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean found for dependency [java.util.Set<javax.persistence.EntityManager>]: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: 
2017-03-13 19:44:42.816  INFO 40010 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2017-03-13 19:44:42.825  INFO 40010 --- [           main] o.apache.catalina.core.StandardService   : Stopping service Tomcat
2017-03-13 19:44:42.860  INFO 40010 --- [           main] utoConfigurationReportLoggingInitializer : 

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-03-13 19:44:42.995 ERROR 40010 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in org.springframework.data.jpa.repository.support.DefaultJpaContext required a bean of type 'java.util.Set' that could not be found.


Action:

Consider defining a bean of type 'java.util.Set' in your configuration.

事实是我没有在我的代码中定义 DefaultJpaContext:

@Configuration
@EnableTransactionManagement
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class DatabaseConfig 

    @Autowired private Environment env;
    @Autowired private DataSource dataSource;
    @Autowired private SessionFactory sessionFactory;

    private static final String DB_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
    private static final String HIBERNATE_DIALECT    = "org.hibernate.dialect.MySQL5Dialect";
    private static final String HIBERNATE_VALIDATION = "validate";
    private static final String SHOW_SQL             = "false";
    private static final String ENTITY_PACKAGE       = MainEntity.class.getPackage().getName();

    final Logger log = LoggerFactory.getLogger(DatabaseConfig.class);


    @Bean
    public DataSource dataSource() 
        final String driverName = env.getProperty("db.driver", DB_DRIVER_CLASS_NAME);
        final String url        = env.getProperty("db.url");
        final String username   = env.getProperty("db.username");
        final String password   = env.getProperty("db.password");
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();

        if (log.isInfoEnabled()) 
            log.info("Database Configuration:");
            log.info("Setting driverName to ", driverName);
            log.info("Setting url to ", url);
            log.info("Setting username to ", username);
            if (StringUtils.isEmpty(password)) log.warn("Password not specified");
            else log.info("Setting password");
        

        dataSource.setDriverClassName(driverName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    

    @Bean
    public LocalSessionFactoryBean sessionFactory()
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setPackagesToScan(new String[] ENTITY_PACKAGE);

        // Hibernate properties
        Properties additionalProperties = new Properties();
        additionalProperties.put("hibernate.dialect"     , env.getProperty("db.dialect"   , HIBERNATE_DIALECT));
        additionalProperties.put("hibernate.hbm2ddl.auto", env.getProperty("db.validation", HIBERNATE_VALIDATION));
        additionalProperties.put("hibernate.show_sql"    , env.getProperty("db.sql.show"  , SHOW_SQL));

        sessionFactory.setHibernateProperties(additionalProperties);
        return sessionFactory;
    

    @Bean
    public HibernateTransactionManager transactionManager()
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory);
        return transactionManager;
    

更新

这是一个 gradle build:

compile('org.springframework.boot:spring-boot-starter-data-jpa')
// ...
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
compile group: 'org.hibernate'        , name: 'hibernate-core'     , version: '5.2.8.Final'
// ...

我错过了什么?

谢谢,大卫。

【问题讨论】:

DefaultJpaContext 在自动配置中定义。按照错误报告中的建议在启用调试的情况下运行以查看详细信息。但是你正在做的事情是不必要的。所有属性都可以在application.properties 中定义,spring-boot 会选择它。 【参考方案1】:

根据 Spring Boot 错误消息,它无法构建构造函数需要 Set&lt;javax.persistence.EntityManager&gt; entityManagersDefaultJpaContext bean。

看起来你的pom.xml(或build.gradle)中有Spring-Data 依赖项,这需要jpa EntityManagerFactory 而你有Hibernate(LocalSessionFactoryBean)的东西。你必须有DefaultJpaContext bean 吗?

【讨论】:

是的,我有 spring-boot-starter-data-jpa 依赖项,但没有可用的 @Transactional 注释。我真的不需要实体管理器,因为我在这个项目中使用了 SessionFactory。 如果您的问题只是 @ Transactional 注释,那么只需添加 spring-tx 作为您的依赖项。这里的重点是尽量减少您声明的依赖关系。这是Spring-boot 的少数缺点之一,我们只是盲目地声明了一堆starters,它们有时会引入很多我们实际上不需要的依赖项。就像你的情况一样,你不需要 JPA,只需要休眠相关的 jar,那么你不需要接触那些 jpa 启动器。

以上是关于从 Migrate 迁移到 Spring MVC 4 + Hibernate5的主要内容,如果未能解决你的问题,请参考以下文章

多模块 Gradle 项目 - 从 Spring-Boot 1.5 迁移到 2.1

Flask从入门到精通之使用Flask-Migrate实现数据库迁移

Spring MVC 从 2.5 到 3.0

从Spring 3到Spring 5的迁移

如何将 Spring Boot 项目迁移到旧 Spring MVC 项目。面临的问题,如何在遗留 Spring MVC 项目中读取 application.properties 文件

MIGRATE