A-A+
SpringBoot2.2整合Hibernate5
销声匿迹了两周,因为内部的培训班要结业了,所以全身心投入,忙了一下。
在这期间,有一个老旧项目的升级,从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了。
以上,如有错误,欢迎指正。
