Springmvc upgrade to springboot2 stepped on the pit

Disclaimer: Delete the jar configuration of springmvc and change it to springboot. If other components rely on springboot, they should be upgraded, and if they should be deleted, they should be deleted. This article only records the pits after the upgrade. Please use Baidu to upgrade the jar required for springboot.

One. Hibernate’s pit

Concept: the relationship between jpa and Hibernate, jpa is the interface, and Hibernate is the implementation.

The code of the yml file configuration database after the upgrade

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://**:3306/**?autoReconnect=true
    username: ****
    password: ****

Because the old code does not directly operate the database with Hibernate, but uses the database operated by Session, the code is as follows:

 @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;

    public Session getSession() {<!-- -->
        return this.sessionFactory.getCurrentSession();
    }

Therefore, the yml configuration file cannot be used directly, and the data source needs to be reconfigured. If it is not suitable, the sessionFactory will be reported as null.
Reconfigure the data source as follows:

import com.zaxxer.hikari.HikariDataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Map;


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories
public class HibernateDataSourceConfig {<!-- -->

    @Autowired
    private JpaProperties jpaProperties;

    @Autowired
    private HibernateProperties hibernateProperties;

    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring. datasource")
    public DataSource dataSource(DataSourceProperties properties) {<!-- -->
// DataSource build = DataSourceBuilder.create(properties.getClassLoader())
// .type(HikariDataSource.class)
// .driverClassName(properties.determineDriverClassName())
// .url(properties.determineUrl())
// .username(properties.determineUsername())
// .password(properties.determinePassword())
//.build();
// return build;
        HikariDataSource dataSource = hikariDataSource();
        dataSource.setDriverClassName(properties.determineDriverClassName());
        dataSource.setJdbcUrl(properties.determineUrl());
        dataSource.setUsername(properties.determineUsername());
        dataSource.setPassword(properties.determinePassword());
        return dataSource;
    }

    private HikariDataSource hikariDataSource(){<!-- -->
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setMinimumIdle(0);
        dataSource.setMaximumPoolSize(10);
        dataSource.setAutoCommit(true);
        dataSource.setIdleTimeout(10000);
        dataSource.setPoolName("DatebookHikariCP");
        dataSource.setMaxLifetime(30000);
        dataSource.setConnectionTimeout(1000);
        dataSource.setConnectionTestQuery("SELECT 1");
        return dataSource;
    }

    @Bean(name = "entityManagerFactoryBean")
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder,@Qualifier("dataSource") DataSource dataSource){<!-- -->
        return builder. dataSource(dataSource)
                .properties(getVendorProperties(dataSource))
                //Set the location of the entity class
                .packages("***")
                .persistenceUnit("")
                .build();
    }


    private Map<String,Object> getVendorProperties(DataSource dataSource){<!-- -->
        // return jpaProperties. getHibernateProperties(dataSource);
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }


    /**
     * EntityManagerFactory is similar to Hibernate's SessionFactory, mybatis' SqlSessionFactory
     * In short, before performing operations, we always need to obtain an EntityManager, which is similar to Hibernate's Session,
     * sqlSession of mybatis.
     * @param builder
     * @return
     */
    @Bean(name = "entityManagerFactory")
    public EntityManagerFactory entityManagerFactory(EntityManagerFactoryBuilder builder,@Qualifier("dataSource") DataSource dataSource){<!-- -->
        return this.entityManagerFactoryBean(builder,dataSource).getObject();
    }


    @Bean(name = "sessionFactory")
    public SessionFactory sessionFactory(EntityManagerFactoryBuilder builder,@Qualifier("dataSource") DataSource dataSource){<!-- -->
        return this.entityManagerFactory(builder,dataSource).unwrap(SessionFactory.class);
    }

    /**
     * Configure transaction manager
     */
    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder, @Qualifier("dataSource") DataSource dataSource){<!-- -->
        return new JpaTransactionManager(entityManagerFactory(builder, dataSource));
    }

}


The data source is managed by Hikari, but configuring Hikari parameters directly in yml does not take effect, so the Hikari parameters are written in the code.

Two. The pit of GeneratedValue

@Id
@GeneratedValue
@Column(
    name = "ID",
    updatable = false
)
private Long id;

The above code is the configuration of the old code. The default configuration of the strategy in GeneratedValue is AUTO, so the direct execution of the save will report an error Table ‘xxx.hibernate_sequence’ doesn’t exist, because the upgrade spring-boot-starter-data-jpa uses hibernate5, solve Method: the following two

spring:
  jpa:
    hibernate:
      use-new-id-generator-mappings: false
@GeneratedValue(strategy = GenerationType.IDENTITY)

The pit of three.request.getParameterMap

As shown above, request.getParameterMap() can get the value in Content-Type: application/x-www-form-urlencoded in springmvc, but cannot get it in springboot2. If the value is obtained in springboot2, the following modification is required.

Enumeration<String> keys = request. getParameterNames();
 Map<String, String[]> resMap = new HashMap<>();
        while (keys.hasMoreElements()){<!-- -->
            String key = keys. nextElement();
            String[] value = request. getParameterValues(key);
            resMap. put(key, value);
        }

After a day of transformation, it is finally over, but I am not sure if there will be other pitfalls, and more tests are needed.