最近编写框架,发现SpringBoot2.X集成hibernate5资料很少,而且大部分都不是很全,目前将自己最近的研究的编写上来供大家参考,大家有什么意见建议欢迎评论。
本人前面配置以及代码使用图片展示,方便圈出注意点,图片中的代码将在文章结尾一一放出。
1.springboot2.x的application.yml的配置文件
注意点在于2.*相较于1.*项目名访问设置不一样了。还有session时间的设置方法,具体的可以看我的注释。
2.application-test.yml文件设置
数据源设置:
与springboot1.x版本相比,不同点就在于配置位置不一样了,还有mysql的驱动也不一样了,用旧也可以但是控制台打印的时候会警告,url后面要带时区,不然启动报错。
jpa设置:
这块很重要,请大家认真看,而且变化也是比较多的地方,这块要配合获取SessionFactory来设置LocalSessionFactoryBean用得,为了实现事务托管给spring处理,目前网上关于这块比较全的资料很少。
3.maven引入
数据库方便的jar主要就是我框出来的。
4.Session获取(重点中的重点)
这个我花了2天研究好的,如果对你有帮助点个赞吧
先看图片:
总共有2中方式,区别地方请看注释,作为框架涉及事务的回滚与提交肯定是采用2种了getCurrentSession。但是要配置LocalSessionFactoryBean,不配置在实体操作的时候会报错。
package com.wt.basics.system.dao.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
/**
* @Copyright (c), 2012-2099 NetWork.Co.,Ltd
* @package
* @FileName:
* @Author:wangtai
* @Date:
* @Description:
* 配置LocalSessionFactoryBean
* @Vesion:1.0
*/
@Configuration
public class HibernateConfig {
@Autowired
private Environment environment;
@Autowired
private DataSource dataSource;
@Bean
public LocalSessionFactoryBean sessionFactoryBean() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
sessionFactoryBean.setPackagesToScan("com.wt");//dao和entity的公共包
sessionFactoryBean.setHibernateProperties(hibernateProperties());
return sessionFactoryBean;
}
//获取hibernate配置
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.current_session_context_class", environment.getProperty("spring.jpa.properties.hibernate.current_session_context_class"));
properties.setProperty("hibernate.hbm2ddl.auto", environment.getProperty("spring.jpa.hibernate.ddl-auto"));
properties.setProperty("hibernate.show-sql", environment.getProperty("spring.jpa.properties.hibernate.show-sql"));
properties.setProperty("hibernate.cache.use_second_level_cache", environment.getProperty("spring.jpa.properties.hibernate.cache.use_second_level_cache"));
properties.setProperty("hibernate.cache.use_query_cache", environment.getProperty("spring.jpa.properties.hibernate.cache.use_query_cache"));
return properties;
}
}
主要注意点就是这个地方:
没错就是读取我没配置文件中jpa的设置,在springboot1.x中不用再用代码设置,直接配置文件就行,但是在2.X中单单设置配置文件中jpa是不行的。还要额外再在LocalSessionFactoryBean设置一遍。
原因是1.x和2.x获取Session的工厂bean是不一样的。
2.x版本使用的是javax.persistence.EntityManagerFactory
1.X版本使用的是org.hibernate.SessionFactory(但是在hibernate5中被废弃了,并且在源码注释中让我没使用javax.persistence.EntityManager,这个可以不获取session来操作hql,有兴趣的小伙伴可以去看看,但是感觉网上文章写得太复杂了。)
这块真的很不甘心,因为相较于1.x还要额外设置LocalSessionFactoryBean,并且其中的setHibernateProperties不能自动读配置的,还要使用代码重新配置进去。个人感觉很麻烦,但是我这块研究了2天,实在想不到什么优化方式,如果大家有请留言。
5.事务的管理
我这里是使用spring的事务管理,还有一种好像是javax的,差不多,但是同一个项目2种不要去混用。
放代码块,看注释。
package com.wt.basics.system.service;
import com.wt.basics.system.exception.SysException;
import org.springframework.transaction.annotation.Transactional;
/**
* 事务隔离级别isolation:
* @Transactional(isolation = Isolation.READ_UNCOMMITTED):读取未提交数据(会出现脏读, 不可重复读) 基本不使用
* @Transactional(isolation = Isolation.READ_COMMITTED):读取已提交数据(会出现不可重复读和幻读)
* @Transactional(isolation = Isolation.REPEATABLE_READ):可重复读(会出现幻读)
* @Transactional(isolation = Isolation.SERIALIZABLE):串行化
*
* 事物传播行为propagation:
* @Transactional(propagation=Propagation.REQUIRED) :如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
* @Transactional(propagation=Propagation.NOT_SUPPORTED) :容器不为这个方法开启事务
* @Transactional(propagation=Propagation.REQUIRES_NEW) :不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
* @Transactional(propagation=Propagation.MANDATORY) :必须在一个已有的事务中执行,否则抛出异常
* @Transactional(propagation=Propagation.NEVER) :必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
* @Transactional(propagation=Propagation.SUPPORTS) :如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
* timeout:该属性用于设置事务的超时秒数,默认值为-1表示永不超时
* readOnly:该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true)
*
* rollbackFor/rollbackForClassName:
* 该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:
* 指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
* 指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
*
* 该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:
* 指定单一异常类名称:@Transactional(rollbackForClassName="RuntimeException")
* 指定多个异常类名称:@Transactional(rollbackForClassName={"RuntimeException","Exception"})
*
* noRollbackFor/noRollbackForClassName:
* 该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:
* 指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)
* 指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
*
*
* @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能
*
*/
@Transactional(rollbackFor= SysException.class)
public class TxService extends TService{
}
6.参考hql的save与search方法
7.以上部分图片代码:
application.yml:
server:
servlet:
#v2.0 设置超时时间 D :天 T:天和小时之间的分隔符 H :小时 M:分钟 S:秒 每个单位都必须是数字,且时分秒顺序不能乱
session:
timeout: 30m
#访问项目名
context-path: /xxx
port: 8060
tomcat:
basedir:
#打开Tomcat访问日志
accesslog:
enabled: true
directory: logs/access/ #或者用绝对路径如 /home/app/logs/access,上面的basedir就可以去掉不用了
prefix: access_log
suffix: .log
file-date-format: .yyyy-MM-dd
pattern: "%t [%I] %{X-Forwarded-For}i %h %l %u %r %s %b %D %m"
#访问日志所在地目录
directory: ./logs
spring:
profiles:
active: test
application-test.yml:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
username: root
password: root
#driverClassName: oracle.jdbc.driver.OracleDriver
#url: jdbc:oracle:thin:@localhost:1521:orcl
driver-class-name: com.mysql.cj.jdbc.Driver
#serverTimezone=UTC 设置时区
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&serverTimezone=UTC
#最小连接数
minIdLe: 5
#最大连接数
maxActive: 30
#解决mysql8小时问题
validationQuery: SELECT 'X'
#空闲链接最小空闲时间
minEvictableIdleTimeMillis: 3000
#空闲连接检查时间间隔
timeBetweenEvictionRunsMillis: 6000
maxWait: 10000
login:
password:
username:
#ORM映射设置,hibernate需要配置jpa
jpa:
hibernate:
#是否自动建表
ddl-auto: update
properties:
hibernate:
#是否自动打印hql对应的sql语句
show-sql: false
#是否格式化sql语句
format-sql: false
#事务交由spring管理
current_session_context_class: org.springframework.orm.hibernate5.SpringSessionContext
cache:
use_second_level_cache: false
use_query_cache: false
maven:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<repositories>
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<groupId>com.wt</groupId>
<artifactId>basicsMyBatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>xxx</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<!--ORM框架需要引入jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- 添加Hibernate支持 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<!-- mysql数据库连接 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.66</version>
</dependency>
<!-- commons-lang3 工具类-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<!-- 日志包-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
HqlDaoImpl.java
package com.wt.basics.system.dao.impl;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManagerFactory;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @Copyright (c), 2012-2019, NetWork.Co.,Ltd
* @package
* @FileName:
* @Author:wangtai
* @Date:
* @Description:
* @Vesion:1.0
*/
@Repository("hqlDao")
public class HqlDaoImpl implements HqlDao {
@Autowired
private EntityManagerFactory entityManagerFactory;
/**
* 开启一个session
* 需要手动开关session
* @return
*/
public Session getSession() {
return entityManagerFactory.unwrap(SessionFactory.class).openSession();
}
/**
* 托管给spring 需要引入一个配置
* @return
*/
public Session getCurrentSession() {
return entityManagerFactory.unwrap(SessionFactory.class).getCurrentSession();
}
}
以上,完成。