A-A+

SpringBoot2.2整合Hibernate5

2020年08月24日 技术, 默认 暂无评论 阅读 4,212 次

销声匿迹了两周,因为内部的培训班要结业了,所以全身心投入,忙了一下。

在这期间,有一个老旧项目的升级,从SpringMVC升级到SpringBoot,从Hibernate4升级到了Hibernate5。

Hibernate这东西,现在用的人是越来越少了,也不知道当年我怎么脑抽了一下,选择了它,估计与当时刚从.NET转到Java这边来有点关系。

去百度搜索SpringBoot和Hibernate,全都是一大堆挂羊头卖狗肉的,挂着Hibernate,然后给你讲JPA。

我就想升个级,所有的代码最好不要改变,继续使用HibernateTemplate,所以只能自己动手,丰衣足食了。

一定要注意的是本文基于SpringBoot的版本为2.2.5.RELEASE

主要的pom文件如下:

<!-- Spring Boot -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>${spring-boot.version}</version>
    <exclusions>
        <!--排除SpringBoot自带的tomcat-->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version>${spring-boot.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>${spring-boot.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
    <version>${spring-boot.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
    <version>${spring-boot.version}</version>
    <scope>provided</scope>
</dependency>

数据源的相关代码如下:

@Configuration
@EnableConfigurationProperties({DBProperties.class, AppProperties.class})
@EnableTransactionManagement
public class DataSourceAutoConfig {

    @Resource
    private DBProperties properties;

    @Primary
    @Bean(name = "dataSource")
    public DataSource getDataSource() throws Exception {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(properties.getDriver());
        dataSource.setUrl(properties.getUrl());
        dataSource.setUsername(properties.getUname());
        dataSource.setPassword(properties.getPassword());
        dataSource.setInitialSize(1);
        dataSource.setMinIdle(1);
        dataSource.setMaxActive(20);
        dataSource.setFilters("stat");
        return dataSource;
    }

    @Primary
    @Bean(name = "transactionManager")
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

    @Primary
    @Bean(name = "transactionTemplate")
    public TransactionTemplate getTransactionTemplate(DataSourceTransactionManager transactionManager) {
        TransactionTemplate transactionTemplate = new TransactionTemplate();
        transactionTemplate.setTransactionManager(transactionManager);
        return transactionTemplate;
    }
}

Hibernate相关的配置如下:

@Configuration
public class HibernateConfig {

    @Resource(name = "dataSource1")
    private DataSource dataSource1;

    @Bean("localSessionFactoryBean1")
    public LocalSessionFactoryBean getLocalSessionFactoryBean1() {
        LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
        localSessionFactoryBean.setDataSource(dataSource1);
        localSessionFactoryBean.setPackagesToScan("com.example");

        Properties properties = new Properties();
        properties.put("hibernate.dialect""org.hibernate.dialect.MySQL5Dialect");
        properties.put("hibernate.show_sql""true");
        properties.put("hibernate.connection.release_mode""auto");
        properties.put("hibernate.current_session_context_class""org.springframework.orm.hibernate5.SpringSessionContext");

        localSessionFactoryBean.setHibernateProperties(properties);
        return localSessionFactoryBean;
    }

    @Bean("hibernateTemplate1")
    public HibernateTemplate getHibernateTemplate1(@Qualifier("localSessionFactoryBean1") LocalSessionFactoryBean localSessionFactoryBean) {
        return new HibernateTemplate(localSessionFactoryBean.getObject());
    }
}

Filter的相关配置如下:

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean getOpenSessionFilter1() {
        FilterRegistrationBean<OpenSessionInViewFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new OpenSessionInViewFilter());
        filterRegistrationBean.setEnabled(true);
        filterRegistrationBean.addUrlPatterns("*");
        filterRegistrationBean.setInitParameters(new HashMap<String, String>() {
            private static final long serialVersionUID = -4377783733248874717L;

            {
                put("sessionFactoryBeanName""localSessionFactoryBean1");
                put("singleSession""true");
                put("flushMode""AUTO");
            }
        });
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }
}

如果是单数据源,以上的配置即可兼容旧的代码了。

但是,我这里的项目是基于多数据源的,之前使用Atomikos进行多数据源的事务管理,所以上面的代码需要改造一部分。

DataSource必须使用XA数据源,代码如下:

@Primary
@Bean(name = "dataSource1")
public DataSource getDataSource1() throws Exception {
    DruidXADataSource druidXaDataSource = new DruidXADataSource();
    druidXaDataSource.setDriverClassName(mySqlDbProperties.getDriver());
    druidXaDataSource.setUrl(mySqlDbProperties.getUrl());
    druidXaDataSource.setPassword(mySqlDbProperties.getPassword());
    druidXaDataSource.setUsername(mySqlDbProperties.getUname());
    druidXaDataSource.setInitialSize(1);
    druidXaDataSource.setMinIdle(1);
    druidXaDataSource.setMaxActive(20);
    druidXaDataSource.setFilters("stat");

    // 数据源改为Atomikos,将事务交给Atomikos统一管理
    AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
    xaDataSource.setXaDataSource(druidXaDataSource);
    xaDataSource.setUniqueResourceName("datasource1");

    return xaDataSource;
}

事务管理部分,也需要使用Atomikos的:

public class TransactionConfig {

    @Bean(name = "userTransaction")
    public UserTransaction userTransaction() throws Throwable {

        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(10000);
        return userTransactionImp;
    }

    @Bean(name = "atomikosTransactionManager")
    public TransactionManager atomikosTransactionManager() {

        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }

    @Bean(name = "transactionManager")
    @DependsOn({"userTransaction""atomikosTransactionManager"})
    public JtaTransactionManager transactionManager(@Qualifier("userTransaction") UserTransaction userTransaction,
                                                    @Qualifier("atomikosTransactionManager") TransactionManager atomikosTransactionManager) throws Throwable 
{
        return new JtaTransactionManager(userTransaction, atomikosTransactionManager);
    }
}

这些都是正常的写法,最关键的在于下方的代码:

@Bean("localSessionFactoryBean1")
public LocalSessionFactoryBean getLocalSessionFactoryBean1() {
    LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
    localSessionFactoryBean.setDataSource(dataSource1);
    localSessionFactoryBean.setPackagesToScan("com.example");

    Properties properties = new Properties();
    properties.put("hibernate.dialect""org.hibernate.dialect.MySQL5Dialect");
    properties.put("hibernate.show_sql""true");
    properties.put("hibernate.connection.release_mode""auto");
    properties.put("hibernate.current_session_context_class""org.springframework.orm.hibernate5.SpringSessionContext");
    //最关键的就是下面这行,如果没有配置,既不报错也不生效
    properties.put("hibernate.transaction.factory_class""org.hibernate.transaction.JTATransactionFactory");

    localSessionFactoryBean.setHibernateProperties(properties);
    return localSessionFactoryBean;
}

@Bean("hibernateTemplate1")
public HibernateTemplate getHibernateTemplate1(@Qualifier("localSessionFactoryBean1") LocalSessionFactoryBean localSessionFactoryBean) {
    return new HibernateTemplate(localSessionFactoryBean.getObject());
}

基本上就是这样,关键点都在上面的代码里面了。如果使用Atomikos,最关键就在那行代码,我是挺服这种Key/Value配置的,猜都猜不到。

吐槽一下,我估计这辈子都不会再用Hibernate了。

以上,如有错误,欢迎指正。

觉的不错?可以关注我的公众号↑↑↑

给我留言

Copyright © 字痕随行 保留所有权利.   Theme  Ality

用户登录

分享到: