【问题标题】:Spring Boot, Hibernate initiates twiceSpring Boot,Hibernate 启动两次
【发布时间】:2023-04-06 08:36:01
【问题描述】:

我在使用 Hibernate 和 Spring Boot 时遇到了问题。 Hibernate 加载了两次,因此它创建了数据库,然后再次重新创建它(使用 hbm2ddl.auto=create,所以我预计一次)。

@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackageClasses = {
        UserMapper.class,
        EventMapper.class,
        GroupMapper.class,

        UserServiceImpl.class,
        EventServiceImpl.class,
        GroupServiceImpl.class,

        UserController.class
})
@PropertySource(value = {"classpath:application.properties"})
@Import({ DatabaseConfig.class })
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

和数据库配置:

@EnableJpaRepositories(basePackageClasses = {
        EventRepository.class,
        GroupRepository.class,
        UserRepository.class
})
@EnableTransactionManagement
public class DatabaseConfig {
    private static final String DB_DRIVER_CLASS = "db.driver";
    private static final String DB_PASSWORD = "db.password";
    private static final String DB_URL = "db.url";
    private static final String DB_USERNAME = "db.username";
    private static final String DB_SSL = "db.ssl";
    private static final String DB_SSL_FACTORY = "db.ssl.factory";
    private static final String DB_FORMAT_SQL = "db.formatSql";
    private static final String DB_DIALECT = "db.dialect";
    private static final String DB_SHOW_SQL = "db.show_sql";
    private static final String DB_HBM2DLL_AUTO = "db.hbm2ddl.auto";
    private static final String DB_POOL_SIZE = "db.poolSize";

    @Resource
    private Environment env;

    @Bean
    public SessionFactory sessionFactory() throws IOException {
        final LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
        factory.setDataSource(dataSource());
        factory.setPackagesToScan(packagesToScan());
        factory.setHibernateProperties(dataSourceProperties());
        factory.setAnnotatedClasses(classesToAdd());
        factory.afterPropertiesSet();
        return factory.getObject();
    }

    private DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getRequiredProperty(DB_DRIVER_CLASS));
        dataSource.setUrl(env.getRequiredProperty(DB_URL));
        dataSource.setUsername(env.getRequiredProperty(DB_USERNAME));
        dataSource.setPassword(env.getRequiredProperty(DB_PASSWORD));
        dataSource.setConnectionProperties(connectionPropertiesDev());
        return dataSource;
    }

    public Class[] classesToAdd() {
        return new Class[]{

        };
    }

    public String[] packagesToScan() {
        return new String[] {""};
    }

    private Properties dataSourceProperties() {
        Properties props = new Properties();
        props.put("hibernate.connection.driver_class", env.getRequiredProperty(DB_DRIVER_CLASS));
        props.put("hibernate.connection.url", env.getRequiredProperty(DB_URL));
        props.put("hibernate.connection.username", env.getRequiredProperty(DB_USERNAME));
        props.put("hibernate.connection.password", env.getRequiredProperty(DB_PASSWORD));
        props.put("hibernate.connection.pool_size", env.getRequiredProperty(DB_POOL_SIZE));
        props.put("hibernate.connection.requireSSL", env.getRequiredProperty(DB_SSL));
        props.put("hibernate.hbm2ddl.auto", env.getRequiredProperty(DB_HBM2DLL_AUTO));
        props.put("hibernate.show_sql", env.getRequiredProperty(DB_SHOW_SQL));
        props.put("hibernate.dialect", env.getRequiredProperty(DB_DIALECT));
        props.put("hibernate.format_sql", env.getRequiredProperty(DB_FORMAT_SQL));
        return props;
    }

    private Properties connectionPropertiesDev() {
        Properties properties = new Properties();
        properties.put("ssl", env.getRequiredProperty(DB_SSL, Boolean.class));
        properties.put("sslfactory", env.getRequiredProperty(DB_SSL_FACTORY));
        return new Properties();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
        entityManagerFactoryBean.setPackagesToScan(packagesToScan());
        entityManagerFactoryBean.setJpaProperties(dataSourceProperties());
        return entityManagerFactoryBean;
    }

    @Bean
    public HibernateTransactionManager transactionManager() throws IOException {
        final HibernateTransactionManager txManager = new HibernateTransactionManager(sessionFactory());
        txManager.afterPropertiesSet();
        return txManager;
    }

}

有人知道为什么会这样吗?

【问题讨论】:

  • 可能是因为您有一个LocalContainerEntityManagerFactoryBean 和一个SessionFactory?你两个都需要吗?您是否需要其中任何一个(因为 Boot 会为您创建一个)?

标签: java spring hibernate spring-boot spring-data-jpa


【解决方案1】:

对于可能与我犯同样错误的其他人,Dave Syer 的答案是正确的。 我检查了http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#appendix 并阅读了整个文档。

只需提供正确的配置值,您就会走得更远。感谢戴夫的帮助。

【讨论】:

    【解决方案2】:

    检查您的 web.xml 文件并确保 spring ApplicationContext 没有被加载两次。确保 contextConfigurationLocation 和 appServlet 不是同一个文件。如果它们是,那么您的应用程序上下文将被加载两次。我在这些行周围有星号。我正在使用调度程序,因为我在这些地方有相同的文件,所以调度的任务运行了两次。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <display-name>FLEX Contacts Mobile Service</display-name>
      <context-param>
        ***<param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml</param-value>***
      </context-param>
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          **<param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/servlet-context.xml</param-value>**
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/flex_contacts_mobile_service/*</url-pattern>
      </servlet-mapping>
    </web-app>
    

    【讨论】:

      猜你喜欢
      • 2019-10-05
      • 1970-01-01
      • 2016-10-22
      • 2015-10-25
      • 1970-01-01
      • 2015-10-13
      • 2020-08-25
      • 1970-01-01
      • 2021-08-18
      相关资源
      最近更新 更多