SpingBoot 2.3.1 integrates Hibernate5 and uses the configuration SessionFactory method to achieve compatibility with BaseDao code

Since SpringBoot 2.3.1 integrates with Hibernate by default, JPA is used, and the JPA specification is not compatible. The lower version of Spring and Hibernate are integrated to implement BaseDao manipulation data reading. Here, compatibility is achieved through manual configuration.
Specific steps:
1. To use hibernate, first need to introduce several dependencies in pom.xml

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

Hibernate is developed using JPA specifications, so spring uses jpa to rely on introducing hibernate. The introduction of jdbc dependency is not necessary.
2. To exclude data source automatic configuration, JPA automatic configuration and hibernateJpa automatic configuration in the @SpringBootApplication annotation of the startup entrance, the
code is as follows:

//启动时将数据源自动配置、JPA自动配置及hibernateJpa自动配置排除掉,如果不排除则将按照springboot的自动设置运行程序,自己写的配置hibernate配置无法生效
@SpringBootApplication(exclude = {
    
    
        DataSourceAutoConfiguration.class,
        JpaRepositoriesAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class })
// 开启事务管理
@EnableTransactionManagement(proxyTargetClass = true)//启用注解事务,即可以使用@Transactional注解来控制事务等同于xml配置方式的 <tx:annotation-driven />
@EnableAspectJAutoProxy//允许AspectJ自动生成代理

public class HibernateproApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(HibernateproApplication.class, args);
    }
}

The function of @EnableTransactionManagement(proxyTargetClass = true) is to enable annotated transactions, that is, you can use @Transactional annotations to control transactions, which is equivalent to the xml configuration mode <tx:annotation-driven />
@EnableAspectJAutoProxy The function is to allow AspectJ to automatically generate proxies and annotate @Aspect The marked component class implements the AOP function.

3. Configure the data source in the application.properties configuration file. The following code uses two data sources to configure multiple data sources

app.datasource.first.driver-class-name=com.mysql.cj.jdbc.Driver
app.datasource.first.jdbc-url=jdbc:mysql://192.168.1.110:3306/lovemall?&serverTimezone=UTC&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
app.datasource.first.username=root
app.datasource.first.password=abc7048461
app.datasource.first.type=com.zaxxer.hikari.HikariDataSource
app.datasource.first.hikari.minimum-idle=5
app.datasource.first.hikari.maximum-pool-size=500
app.datasource.first.hikari.auto-commit=true
app.datasource.first.hikari.idle-timeout=30000
app.datasource.first.hikari.pool-name=DatebookHikariCP1
app.datasource.first.hikari.max-lifetime=1800000
app.datasource.first.hikari.connection-timeout=30000
app.datasource.first.hikari.connection-test-query=SELECT 1

app.datasource.second.driver-class-name=com.mysql.cj.jdbc.Driver
app.datasource.second.jdbc-url=jdbc:mysql://192.168.1.110:3306/lovemall?&serverTimezone=UTC&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
app.datasource.second.username=root
app.datasource.second.password=abc7048461
app.datasource.second.type=com.zaxxer.hikari.HikariDataSource
app.datasource.second.hikari.minimum-idle=5
app.datasource.second.hikari.maximum-pool-size=500
app.datasource.second.hikari.auto-commit=true
app.datasource.second.hikari.idle-timeout=30000
app.datasource.second.hikari.pool-name=DatebookHikariCP2
app.datasource.second.hikari.max-lifetime=1800000
app.datasource.second.hikari.connection-timeout=30000
app.datasource.second.hikari.connection-test-query=SELECT 1

The springboot2.X version uses the hikari connection pool to connect to the database by default. The hikari attribute is configured in the configuration file. It should be noted that the high version of the mysql connector driver is replaced with com.mysql.cj.jdbc.Driver .
4. Realize the configuration of the data source, declare a java configuration class separately, and configure the beans of the two data sources

@Configuration
public class HibernateDataSourceConfig {
    
    
    //第一个数据源
    @Bean(name = "firstDataSource")
    @ConfigurationProperties(prefix = "app.datasource.first")//application.properties文件中前缀配置引用
    @Primary//多个数据源时首先注入
    public DataSource firstDataSource() {
    
    
        return DataSourceBuilder.create().build();
    }
    //第二个数据源
    @Bean(name="secondDataSource")
    @ConfigurationProperties(prefix="app.datasource.second")//application.properties文件中前缀配置引用
    public DataSource secondDataSource() {
    
    
        return DataSourceBuilder.create().build();
    }
}

It can be seen from the code that the two data source beans are added to the spring container for management, the first data source is the default data source name firstDataSource, and the second data source name is secondDataSource.
5. Use data source injection to configure Hibernate's SessionFactory, the code is as follows

@Configuration
public class HibernateSessionConfig {
    
    

    //注入第一个数据源,生成sessionFactory
    @Autowired
    @Bean("sessionFactory")
    @Primary
    public LocalSessionFactoryBean getSessionFactory(@Qualifier("firstDataSource")DataSource dataSource) {
    
    
        return buildLocalSessionFactory(dataSource);
    }

    /**
     * 设置Hibernate的配置属性
     * @return
     */
    private Properties getHibernateProperties(){
    
    
        Properties hibernateProperties = new Properties();
        hibernateProperties.put("hibernate.dialect","org.hibernate.dialect.MySQL55Dialect");
        hibernateProperties.put("current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext");
        hibernateProperties.put("hibernate.show_sql", "true");
        hibernateProperties.put("hibernate.format_sql", "false");
        hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
        return hibernateProperties;
    }

    /**
     * 构建LocalSessionFactoryBean实例
     * @param dataSource 构建实例所使用的的数据源
     * @return
     */
    private LocalSessionFactoryBean buildLocalSessionFactory(DataSource dataSource){
    
    
        LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
        localSessionFactoryBean.setDataSource(dataSource); // 配置数据源,指定成第一个数据源
        // 如果使用 xml 配置则使用该方法进行包扫描
        //PathMatchingResourcePatternResolver pmprpr = new PathMatchingResourcePatternResolver();
        //Resource[] resource = pmprpr.getResources("classpath*:com/ml/hibernatepro/ml/domain/*.hbm.xml");
        //localSessionFactoryBean.setMappingLocations(resource);

        // 现在配置基本都切换到 java config
        //localSessionFactoryBean.setAnnotatedPackages("classpath*:com/ml/hibernatepro/ml/domain");
        // 添加 Hibernate 配置规则
        localSessionFactoryBean.setHibernateProperties(getHibernateProperties());
        //指定需要扫描的hibernate的Entity实体类包名,可以指定多个包名
        localSessionFactoryBean.setPackagesToScan("com.ml.hibernatepro.ml.domain");
        return localSessionFactoryBean;
    }
    //注入第二个数据源生成secondSessionFactory
    @Autowired
    @Bean("secondSessionFactory")
    public LocalSessionFactoryBean getSecondSessionFactory(@Qualifier("secondDataSource")DataSource dataSource) {
    
    
        return buildLocalSessionFactory(dataSource);
    }
}

Through code analysis, it can be seen that the LocalSessionFactoryBean is used in the configuration class to generate the SessionFactory. The specific implementation is consistent with the adaptation of the XML configuration file parameter configuration in the lower version of spring, except that the XML configuration is replaced with the java configuration.
The code uses the first data source firstDataSource to generate a sessionFactory, and uses the second data source secondDataSource to generate a secondSessionFactory. Both hibernate session factories are added to the spring container for management.
6. Use the two session factory beans generated in the previous step to configure two transaction managers respectively. Note that the transaction configuration class inherits the TransactionManagementConfigurer interface. The function of this interface is to specify a default transaction manager. When using the annotation @Transactional, no transaction management is specified Name, the default transaction manager is automatically enabled. If a name is specified, the specified transaction manager will be activated according to the name.

@Configuration
public class TransactionConfig implements TransactionManagementConfigurer {
    
    
    //注入基于第一个数据源生成的会话工厂
    @Autowired
    @Qualifier("sessionFactory")
    private  SessionFactory sessionFactory;

    // 事务管理交给 HibernateTransactionManager
    //基于第一个数据源的事务管理
    @Bean("transactionManager")
    public HibernateTransactionManager getTransactionManager(){
    
    
        HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager();
        hibernateTransactionManager.setSessionFactory(sessionFactory);
        return hibernateTransactionManager;
    }
    //实现接口 TransactionManagementConfigurer 方法,其返回值代表默认使用的事务管理器
    //注意,此处返回的事务管理器就是@Transactional的默认值,如果不返回则需要指明@Transactional使用的事务管理器名称
    //多事务管理器时指明@Transactional(value="transactionManager"),则代表使用的那个事务
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
    
    
        return getTransactionManager();
    }
    //注入基于第二个数据源生成的会话工厂
    @Autowired
    @Qualifier("secondSessionFactory")
    private SessionFactory secondSessionFactory;
    // 事务管理交给 HibernateTransactionManager
    @Bean("queryTransactionManager")
    public HibernateTransactionManager queryTransactionManager(){
    
    
        HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager();
        hibernateTransactionManager.setSessionFactory(secondSessionFactory);
        return hibernateTransactionManager;
    }
    //DAO中使用的组件实例,在service中使用,主从数据库时负责查询
    @Bean(name="queryDaoBulider")
    public QueryDaoBuilder queryDaoBuilder(){
    
    
        QueryDaoBuilder daoBuilder=new QueryDaoBuilder();
        daoBuilder.setSessionFactory(secondSessionFactory);
        return daoBuilder;
    }
    //DAO中使用的组件实例,在service中使用
    @Bean(name="daoBuilder")
    public DaoBuilder daoBuilder(){
    
    
         DaoBuilder daoBuilder=new DaoBuilder();
         daoBuilder.setSessionFactory(sessionFactory);
         return daoBuilder;
     }

}

The last two Beans in the code, daoBuilder and queryDaoBulider, are used in my BaseDao interface, so you don't need to refer to them. Up to this point, it has been fully realized that it does not use the JPA specification to integrate with Hibernate, and the use of Hibernate is consistent with the traditional BaseDao.
Note: In the package and sub-package where the @SpringBootApplication annotated class is located, the annotated classes such as @Service, @Component, @Entity can be directly scanned and added to the spring container for management. If the hibernate and other java files you write are not in the previously mentioned location, please use @ComponentScan(value = "io.mieux.controller") annotation at the startup entrance, you can add multiple package scans to the container, @ComponentScan annotation is equivalent The previous context: component-scan.

Guess you like

Origin blog.csdn.net/u011930054/article/details/106856750