本篇介绍如何在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/
文章评论