目录
引入 Druid Spring Boot Starter 依赖
一、SpringBoot JDBC访问数据库
对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 都默认采用整合 Spring Data 的方式进行统一处理,通过大量自动配置,来简化我们对数据访问层的操作,我们只需要进行简单的设置即可实现对书层的访问。
引入JDBC启动器
<!--导入JDBC的启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
数据库驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
配置数据源
# 数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/db1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
spring.datasource.username=root
spring.datasource.password=root
测试
Spring Boot 提供了一个名为 JdbcTemplate 的轻量级数据访问工具,它是对 JDBC 的封装。Spring Boot 对 JdbcTemplate 提供了默认自动配置,我们可以直接使用 @Autowired 或构造函数将它注入到 bean 中使用。
@RestController
public class Demo {
//注入jdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@GetMapping("/test")
public Map test(){
String sql = "select * from users where id = ?";
Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap(sql, 1);
return stringObjectMap;
}
@GetMapping("/test1")
public List test1(){
String sql = "select * from users where id > ?";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, 1);
return list;
}
}
二、Spring Boot整合Druid数据源
Druid 是阿里巴巴推出的一款开源的高性能数据源产品,Druid 支持所有 JDBC 兼容的数据库,包括 Oracle、MySQL、SQL Server 和 H2 等等。Druid 不仅结合了 C3P0、DBCP 和 PROXOOL 等数据源产品的优点,同时还加入了强大的监控功能。通过 Druid 的监控功能,可以实时观察数据库连接池和 SQL 的运行情况,帮助用户及时排查出系统中存在的问题。
使用 Druid Spring Boot Starter 将 Druid 与 Spring Boot 整合
引入 Druid Spring Boot Starter 依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.9</version>
</dependency>
配置属性
#数据库连接信息配置
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/shop
druid:
initial-size: 10 # 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
min-idle: 10 # 最小连接池数量 最小空闲数量
maxActive: 200 # 最大连接池数量 最大活跃连接数
maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置
timeBetweenEvictionRunsMillis: 60000 # 检查空闲连接的频率.Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。
minEvictableIdleTimeMillis: 300000 # 连接的最小生存时间.连接保持空闲而不被驱逐的最小时间
validationQuery: SELECT 1 # 验证数据库服务可用性的sql.用来检测连接是否有效的sql 因数据库方言而差, 例如 oracle 应该写成 SELECT 1 FROM DUAL
testWhileIdle: true # 申请连接时检测空闲时间,根据空闲时间再检测连接是否有效.建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRun
testOnBorrow: false # 申请连接时直接检测连接是否有效.申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturn: false # 归还连接时检测连接是否有效.归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
poolPreparedStatements: true # 开启PSCache
maxPoolPreparedStatementPerConnectionSize: 20 #设置PSCache值
connectionErrorRetryAttempts: 3 # 连接出错后再尝试连接三次
breakAfterAcquireFailure: true # 数据库服务宕机自动重连机制
timeBetweenConnectErrorMillis: 300000 # 连接出错后重试时间间隔
asyncInit: true # 异步初始化策略
remove-abandoned: true # 是否自动回收超时连接
remove-abandoned-timeout: 1800 # 超时时间(以秒数为单位) 超过此值后,druid将强制回收该连接
transaction-query-timeout: 6000 # 事务超时时间
filters: stat,wall,log4j2
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
stat-view-servlet:
enabled: true #是否开启内置监控页面,默认值为 false
url-pattern: "/druid/*" #StatViewServlet 的映射路径,即内置监控页面的访问地址
allow: 127.0.0.1 #白名单
deny: #黑名单
reset-enable: false #是否启用重置按钮
login-username: admin #内置监控页面的登录页用户名 username
login-password: admin #内置监控页面的登录页密码 password
web-stat-filter:
enabled: true #是否开启内置监控中的 Web-jdbc 关联监控的数据
url-pattern: "/*" #匹配路径
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*" #排除路径
session-stat-enable: true #是否监控session
三、Spring Boot整合MyBatis
MyBatis 是一个半自动化的 ORM 框架,所谓半自动化是指 MyBatis 只支持将数据库查出的数据映射到 POJO 实体类上,而实体到数据库的映射则需要我们自己编写 SQL 语句实现,相较于Hibernate 这种完全自动化的框架,Mybatis 更加灵活,我们可以根据自身的需求编写 sql 语句来实现复杂的数据库操作。
随着 Spring Boot 越来越流行,越来越多的被厂商及开发者所认可,MyBatis 也开发了一套基于 Spring Boot 模式的 starter:mybatis-spring-boot-starter。
引入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
配置 MyBatis
server.port=8080
spring.profiles.active=dev
#映射文件所在位置
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
#别名
mybatis.type-aliases-package=com.cs.bean
#配置日志级别 com.chensir debug 输出sql信息
logging.level.com.chensir=debug
示例
启动类需加@MapperScan
GoodsController.java
@RestController
public class GoodsController {
@Autowired
GoodsService goodsService;
@GetMapping("/query")
public List query(){
return goodsService.query();
}
}
GoodsServiceImpl.java
@Service
public class GoodsService {
@Autowired
GoodsDao goodsDao;
@Override
public List query() {
return goodsDao.query();
}
}
GoodsDao.java
@Mapper
public interface GoodsMapper {
public List query();
}
GoodsMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chensir.mapper.GoodsMapper">
<select id="select" resultType="List">
select * from account
</select>
<update id="minusMoney">
update account set money = money - #{myMoney} where name = #{from}
</update>
<update id="addMoney">
update account set money = money + #{myMoney} where name = #{to}
</update>
</mapper>
四、Spring Boot事务
在spring boot中 要使用事物 直接使用注解@Transactional既可,无需要做其它任何配置。是因为默认已经开启:
@SpringBootApplication
@MapperScan
//开启事务注解,通过注解标记事务
@EnableTransactionManagement
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
事务失效的几种情况
一、非public修饰的方法
@Transactional注解只能在在public修饰的方法下使用。
/**
* 私有方法上的注解,不生效(因私有方法Spring扫描不到该方法,所以无法生成代理)
*/
@Transactional
private boolean test() {
//test code
}
二、类内部访问
类内部非直接访问带注解标记的方法 B,而是通过类普通方法 A,然后由 A 调用 B。
@Service
public class Demo {
public void A() {
this.B();
}
@Transactional
public void B() {
......
}
}
三、数据库不支持事务
MySQL中,MyISAM引擎不支持事物,InnoDB 支持事物
四、异常类型不匹配
@Transactional 注解默认只处理运行时异常( RuntimeException 和 error),而不会处理受检异常( Exception 的子类)。当抛出未被捕获的运行时异常时,Spring 会触发事务回滚操作,将之前的操作撤销;而对于未被捕获的受检异常,Spring 不会触发事务回滚操作。如果需要处理受检异常并触发事务回滚,可以通过 rollbackFor 和 noRollbackFor 属性来指定需要回滚或不需要回滚的异常类型。
/**
* 非运行异常,且没有通过 rollbackFor 指定抛出的异常,不生效
*
* @param id
* @return
* @throws Exception
*/
@Transactional
public boolean testException(int id) throws Exception {
//运行代码
throw new Exception("参数异常");
}
这种情况需指定异常,如:
@Transactional(rollbackFor = Exception.class)
五、传播属性设置问题
propagation属性错误
@Transactional默认的事务传播机制是:REQUIRED,若指定成了NOT_SUPPORTED、NEVER事务传播机制,则事物不生效,如:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
六、捕获异常未抛出
@Transactional
public void A(){
try{
......
}catch(Exception e){
// 未抛异常
}
}
七、Bean没有纳入Spring容器管理
// 注释调@Component,该类没被Spring管理,事物也是不生效的
// 注释调@Component,该类没被Spring管理,事物也是不生效的
public class Demo {
@Transactional(rollbackFor = Exception.class)
public void A() {
......
}
}
八、事务方法内启动新线程进行异步操作
@Transactional(rollbackFor= BizException.class)
public int transfer2(String from,String to, int money){
accountDao.decrMoney(from,money);
new Thread(()->{
int c = 5/0;
accountDao.addMoney(to,money);
}).start();
return 1;
}