本篇介绍如何在SpringBoot下整合Hibernate,数据操作层不使用JPA,而是使用Hibernate,并实现事物管理(Transaction),以MySQL为例,其他数据库只要修改相关的Connector即可。
pom增加依赖
pom.xml增加hibernate相关,如下,主要增加hibernate, mysql:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.terrynow</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test</name>
<description>test</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties修改
增加数据源datasource的配置,以及hibernate的一些配置如下:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/test_db?allowPublicKeyRetrieval=true&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password= spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=none spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
SpringApplication修改
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Properties;
// 排除 DataSource, JPARepositories, HibernateJpa 的自动配置
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class,
HibernateJpaAutoConfiguration.class })
// 开启事务管理
@EnableTransactionManagement(proxyTargetClass = true)
public class MyApplication extends SpringBootServletInitializer {
@Autowired
private Environment env;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MyApplication.class);
}
@Bean(name = "dataSource")
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
// application.properties 要有相数据源的配置
dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));
dataSource.setPassword(env.getProperty("spring.datasource.password"));
return dataSource;
}
@Autowired
@Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(DataSource dataSource) throws Exception {
Properties properties = new Properties();
// application.properties 要有相关hibernate的配置
properties.put("hibernate.dialect", env.getProperty("spring.jpa.properties.hibernate.dialect"));
properties.put("hibernate.show_sql", env.getProperty("spring.jpa.show-sql"));
properties.put("current_session_context_class", env.getProperty("spring.jpa.properties.hibernate.current_session_context_class"));
// Fix Postgres JPA Error:
// Method org.postgresql.jdbc.PgConnection.createClob() is not yet implemented.
// properties.put("hibernate.temp.use_jdbc_metadata_defaults",false);
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
// 这里修改下,改成需要扫描Entity的类
factoryBean.setPackagesToScan(new String[]{"com.terrynow.app.entity"});
factoryBean.setDataSource(dataSource);
factoryBean.setHibernateProperties(properties);
factoryBean.afterPropertiesSet();
//
SessionFactory sf = factoryBean.getObject();
return sf;
}
@Autowired
@Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
}
新建DAO类
interface接口类,我就省略不写了
@Component("systemDao")
public class SystemDaoImpl implements ISystemDao {
@Autowired
private SessionFactory sessionFactory;
@Override
public Account getAccountById(long accountId) {
return sessionFactory.getCurrentSession().get(Account.class, accountId);
}
}
新建Service类
同样interface省略,这里是可以进行事物处理的,如果操作多个dao,可以自动进行事物提交和回滚。
@Service("systemService")
@Transactional(readOnly = false)
@Repository
public class SystemServiceImpl implements ISystemService {
private static final Log log = LogFactory.getLog(SystemServiceImpl.class);
@Resource(name = "systemDao")
private ISystemDao systemDao;
@Override
public Account getAccount(long accountId) {
//简单起见,随便操作一下数据库
return systemDao.getAccountById(accountId);
}
}
调用service
接下来就可以在controller中调用service了
@RestController
@RequestMapping("/system")
public class SystemController {
@Resource(name = "systemService")
private ISystemService systemService;
@RequestMapping("/test")
public ModelAndView test(@RequestParam(value = "id", required = true) long id) {
ModelAndView model = new ModelAndView();
model.addObject("account", systemService.getAccountById(id))
model.setViewName("/test");
return model;
}
}
如果有多个数据源需要连接,可以看这篇文章:https://blog.terrynow.com/2022/01/28/springboot-hibernate-multiple-datasource-implement/
文章评论