春季启动期间,JpaTransactionManager崩溃而没有错误

时间:2019-06-14 05:12:07

标签: spring hibernate maven spring-boot jpa

我正在使用Hibernate从基于Spring的Web应用程序连接到AWS Aurora集群。 当我在本地和TEST env中运行它时,一切正常,但是在PROD环境中,Web应用程序崩溃了,没有任何错误。由于两种环境在休眠/数据库连接方面使用相同的配置,因此我怀疑Maven依赖问题或Spring中的某些奇怪配置错误。

也试图从构建机器上删除m2缓存,但无济于事。

来自应用程序的日志:

INFO  2019-06-14 04:14:23.173 UTC message="Root WebApplicationContext: initialization completed in 5391 ms" 
INFO  2019-06-14 04:14:24.590 UTC message="Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1992eaf4: startup date [Fri Jun 14 04:14:17 UTC 2019]; root of context hierarchy" 
INFO  2019-06-14 04:14:24.883 UTC message="Initializing connection to Aurora DB with url="jdbc:mysql://*****.us-east-2.rds.amazonaws.com:3306/****?zeroDateTimeBehavior=CONVERT_TO_NULL", username="****", driverClassName="com.mysql.cj.jdbc.Driver"" 
INFO  2019-06-14 04:14:24.951 UTC message="Connection to Aurora DB initialized successfully with url="jdbc:mysql://******.us-east-2.rds.amazonaws.com:3306/****?zeroDateTimeBehavior=CONVERT_TO_NULL", username="****"" 
INFO  2019-06-14 04:14:25.120 UTC message="LocalContainerEntityManagerFactoryBean initialized successfully." 
INFO  2019-06-14 04:14:25.209 UTC message="Building JPA container EntityManagerFactory for persistence unit 'default'" 
INFO  2019-06-14 04:14:25.274 UTC message="HHH000204: Processing PersistenceUnitInfo [name: default]" 
INFO  2019-06-14 04:14:25.513 UTC message="HHH000412: Hibernate Core {5.4.2.Final}" 
WARN  2019-06-14 04:14:25.779 UTC message="HHH020100: The Ehcache second-level cache provider for Hibernate is deprecated.  See https://hibernate.atlassian.net/browse/HHH-12441 for details." 
INFO  2019-06-14 04:14:25.807 UTC message="HCANN000001: Hibernate Commons Annotations {5.1.0.Final}" 

应用程序随后崩溃,没有其他信息/异常。

配置

import org.apache.commons.lang3.StringUtils;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;

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

@Configuration
@EnableTransactionManagement
public class HibernateConfiguration {

    private final Logger logger = LoggerFactory.getLogger(HibernateConfiguration.class);

    @Value("${data.hibernate.verbose:true}")
    private boolean hibernateShowSql;

    @Value("${data.hibernate.packagesToScan:com.myapp}")
    private String packagesToScan;

    @Value("${data.hibernate.dialect:org.hibernate.dialect.MySQL5InnoDBDialect}")
    private String hibernateDialect;

    @Value("${data.hibernate.cache.secondLevel.enable:true}")
    private boolean enableSecondLevelCache;

    @Value("${data.hibernate.cache.query.enable:true}")
    private boolean enableQueryLevelCache;

    @Value("${data.hibernate.cache.class:org.hibernate.cache.ehcache.EhCacheRegionFactory}")
    private String cacheFactoryClass;

    @Value("${myapp.datasource.url:null}")
    private String dbUrl;

    @Value("${myapp.datasource.username:null}")
    private String dbUsername;

    @Value("${myapp.datasource.password:null}")
    private String dbPassword;

    @Value("${myapp.datasource.driverClassName:com.mysql.cj.jdbc.Driver}")
    private String sqlDriverClass;

    private static final String PROPERTY_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_SHOW_SQL = "hibernate.show_sql";
    private static final String PROPERTY_CACHE_FACTORY_CLASS = "hibernate.cache.region.factory_class";
    private static final String PROPERTY_USE_SECOND_LEVEL_CACHE = "hibernate.cache.use_second_level_cache";
    private static final String PROPERTY_USE_QUERY_CACHE = "hibernate.cache.use_query_cache";

    @Bean
    @Lazy
    public DataSource dataSource() {
        logger.info("Initializing connection to Aurora DB with url=\"{}\", username=\"{}\", driverClassName=\"{}\"", dbUrl, dbUsername, sqlDriverClass);
        if (StringUtils.isBlank(dbUrl) || StringUtils.isBlank(dbUsername) || StringUtils.isBlank(dbPassword)) {
            logger.error("SEVERE misconfiguration in connection to DB url=\"{}\", username=\"{}\" passwordIsBlank={}", dbUrl, dbUsername, StringUtils.isBlank(dbPassword));
        }
        DataSource dataSource = DataSourceBuilder.create()
                .url(dbUrl)
                .username(dbUsername)
                .password(dbPassword)
                .driverClassName(sqlDriverClass)
                .build();
        logger.info("Connection to Aurora DB initialized successfully with url=\"{}\", username=\"{}\"", dbUrl, dbUsername);
        return dataSource;
    }

    @Bean
    @Lazy
    public JpaTransactionManager jpaTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
        logger.info("JpaTransactionManager initialized successfully.");
        return transactionManager;
    }

    @Bean
    @Lazy
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setJpaVendorAdapter(vendorAdaptor());
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
        entityManagerFactoryBean.setPackagesToScan(packagesToScan.split(","));
        entityManagerFactoryBean.setJpaProperties(jpaHibernateProperties());
        logger.info("LocalContainerEntityManagerFactoryBean initialized successfully.");
        return entityManagerFactoryBean;
    }

    @Bean
    @Lazy
    public HibernateConnection hibernateConnection() {
        HibernateConnection hibernateConnection = new HibernateConnection(entityManagerFactoryBean().getObject().createEntityManager());
        logger.info("HibernateConnection initialized successfully.");
        return hibernateConnection;
    }

    private HibernateJpaVendorAdapter vendorAdaptor() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setShowSql(true);
        return vendorAdapter;
    }

    private Properties jpaHibernateProperties() {
        Properties properties = new Properties();
        properties.put(PROPERTY_SHOW_SQL, hibernateShowSql);
        properties.put(PROPERTY_DIALECT, hibernateDialect);
        properties.put(PROPERTY_CACHE_FACTORY_CLASS, cacheFactoryClass);
        properties.put(PROPERTY_USE_QUERY_CACHE, enableQueryLevelCache);
        properties.put(PROPERTY_USE_SECOND_LEVEL_CACHE, enableSecondLevelCache);
        return properties;
    }

}

POM:

        <properties>
            <dependency.version.mfa-core-service>0.3.7</dependency.version.mfa-core-service>
            <dependency.version.spring-orm>4.3.7.RELEASE</dependency.version.spring-orm>
            <dependency.version.mysql-connector>8.0.11</dependency.version.mysql-connector>
            <dependency.version.hibernate>5.4.2.Final</dependency.version.hibernate>
        <dependency.version.commons-dbcp2>2.1.1</dependency.version.commons-dbcp2>
        </properties>
        ...
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${dependency.version.spring-orm}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${dependency.version.mysql-connector}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${dependency.version.hibernate}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>${dependency.version.commons-dbcp2}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>5.4.2.Final</version>
        </dependency>

用法:

public class HibernateConnection {

    @PersistenceContext
    private final EntityManager entityManager;

    public HibernateConnection(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
    ....
}

编辑: 我启用了DEBUG。在PROD env上,我在崩溃之前获取了这些日志:

DEBUG 2019-06-14 05:48:48.487 UTC message="Registering IdentifierGenerator strategy [sequence-identity] -> [org.hibernate.id.SequenceIdentityGenerator]" 
DEBUG 2019-06-14 05:48:48.487 UTC message="Registering IdentifierGenerator strategy [enhanced-sequence] -> [org.hibernate.id.enhanced.SequenceStyleGenerator]" 
DEBUG 2019-06-14 05:48:48.489 UTC message="Registering IdentifierGenerator strategy [enhanced-table] -> [org.hibernate.id.enhanced.TableGenerator]" 

在TEST env中,我继续启动并得到以下日志:

DEBUG 2019-06-14 05:25:34.502 UTC message="Registering IdentifierGenerator strategy [sequence-identity] -> [org.hibernate.id.SequenceIdentityGenerator]" 
DEBUG 2019-06-14 05:25:34.502 UTC message="Registering IdentifierGenerator strategy [enhanced-sequence] -> [org.hibernate.id.enhanced.SequenceStyleGenerator]" 
DEBUG 2019-06-14 05:25:34.516 UTC message="Registering IdentifierGenerator strategy [enhanced-table] -> [org.hibernate.id.enhanced.TableGenerator]" 
Fri Jun 14 05:25:37 UTC 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Fri Jun 14 05:25:43 UTC 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
DEBUG 2019-06-14 05:25:46.563 UTC message="Database ->
           name : MySQL
        version : 5.7.12
          major : 5
          minor : 7" 
DEBUG 2019-06-14 05:25:46.563 UTC message="Driver ->
           name : MySQL Connector/J
        version : mysql-connector-java-8.0.11 (Revision: 6d4eaa273bc181b4cf1c8ad0821a2227f116fedf)
          major : 8
          minor : 0" 
DEBUG 2019-06-14 05:25:46.563 UTC message="JDBC version : 4.2" 

因此,似乎一旦建立与数据库的连接,应用程序就会崩溃。

1 个答案:

答案 0 :(得分:0)

因此,很明显,URL指向配置了一个不包含我的服务器的安全组的群集。静默故障是有问题的,但是\\((ツ)_ /¯