Spring操作数据库
1、最基本的操作
引入最基本的数据库驱动,H2(H2是一个Java编写的关系型数据库,它可以被嵌入Java应用程序中使用,或者作为一个单独的数据库服务器运行。),使用JDBC连接数据库。
操作步骤,还是在https://start.spring.io/ 网站进行初始化项目,选中需要的依赖之后下载项目,看一下项目的结构
└─demo
│ .gitignore
│ HELP.md
│ mvnw
│ mvnw.cmd
│ pom.xml
│
├─.mvn
│ └─wrapper
│ maven-wrapper.jar
│ maven-wrapper.properties
│ MavenWrapperDownloader.java
│
└─src
├─main
│ ├─java
│ │ └─com
│ │ └─example
│ │ └─demo
│ │ DemoApplication.java
│ │
│ └─resources
│ application.properties
│
└─test
└─java
└─com
└─example
└─demo
DemoApplicationTests.java
从这里可以看出以下内容
- pom文件
- main类,springboot项目的入口类
- test类
- 其他的,比如.gitignore.maven相关内容等
再看一下POM中的内容
<?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 http://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.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
我们可以很清晰的看到,springboot生成的这个项目里面有以下几个内容
- 定义java版本
- 正确的引入了 actuator,h2,jdbc等依赖。
- 使用了springboot的maven插件,会打成可执行的jar。
我使用了idea导入了我刚才在网站生成的项目,导入方式为maven
。
简单改造了一下项目的入口类,看一下获取的驱动
package com.example.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private DataSource dataSource;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
private void getConn() throws SQLException{
logger.info(dataSource.toString());
Connection conn = dataSource.getConnection();
logger.info(conn.toString());
}
@Override
public void run(String... args) throws Exception {
getConn();
}
}
看到输出结果是
2019-08-16 21:57:36.469 INFO 664 --- [ main] ication$$EnhancerBySpringCGLIB$$3b859d7a : HikariDataSource (null)
2019-08-16 21:57:36.469 INFO 664 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-08-16 21:57:36.560 INFO 664 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-08-16 21:57:36.562 INFO 664 --- [ main] ication$$EnhancerBySpringCGLIB$$3b859d7a : HikariProxyConnection@178575564 wrapping conn0: url=jdbc:h2:mem:testdb user=SA
2019-08-16 21:57:38.749 INFO 664 --- [)-192.168.1.113] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-08-16 21:57:38.749 INFO 664 --- [)-192.168.1.113] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-08-16 21:57:38.756 INFO 664 --- [)-192.168.1.113] o.s.web.servlet.DispatcherServlet : Completed initialization in 7 ms
看到了数据库的连接信息,并且连接池使用的是SpringBoot2.x默认的hikali
连接池,要知道在spring 4.x也就是springboot2.x之前,使用的是tomcat的datasource连接池。
我在初始化项目的时候加入了spring-actuator依赖,这时候访问http://localhost:8080/actuator
结果如下
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"health-component": {
"href": "http://localhost:8080/actuator/health/{component}",
"templated": true
},
"health-component-instance": {
"href": "http://localhost:8080/actuator/health/{component}/{instance}",
"templated": true
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"info": {
"href": "http://localhost:8080/actuator/info",
"templated": false
}
}
}
其实通过这个操作,需要了解的是,springboot为我们做了那些事情
- 通过DataSourceAutoConfiguration 为我们配置了数据源
- 通过DataSourceTransactionManagerAutoConfiguration为我们配置了数据源的事务管理
- 通过JdbcTemplateAutoConfiguration为我们配置了JdbcTemplate
- 以上只有当符合条件的时候才会去自动配置、
2、配置多个数据源
- 将两个数据源的配置分开。
- 告知系统需要去操作哪一个数据源。
- @Primary 作为主要bean。
- 自己在代码中控制 DataSourceAutoConfiguration,DataSourceTransctionManagerAutoConfiguration,JdbcTemplateAutoConfiguration失效(在springbootApplication中加入exclude),自己来完成这三个的bean创建(使用@Bean)。
3、数据库连接池
3.1、hikaliCP
HiukaliCP来自于日语,意思是光,就是快的意思。具体内容可以参考http://brettwooldridge.github.io/HikariCP/
为什么那么快?
-
字节码级别的优化 (很多方法都是通过JavaAssist生成)
-
大量的一些小的改动
- 用自己封装的一个FastStatementList代替了Arraylist
- 无锁的集合ConcurrentBag
- 代理类的优化
在SpringBoot中默认的数据源就是Hikali。
常用的一些配置
spring.datasource.hikali.maximumPoolSize=10 spring.datasource.hikali.minimumidle=10 spring.datasource.hikali.idleTimeout=600000 spring.datasource.hikali.connectionTimeout=30000 spring.datasource.hikali.maxLifetime=180000
3.2、AlibabaDruid
Druid学习和使用指导的地址:druid
Druid是阿里巴巴开源的数据库连接池项目,Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能,功能强大,可以防止sql的注入,内置的Logging可以诊断Hack应用应为。
主要功能项
- 详细的监控
- ExceptionSorter针对主流数据库的返回码都有支持
- SQL防注入
- 内置的加密配置
- 众多的扩展点,方便进行定制。
如何使用
-
引入pom
<!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.19</version> </dependency>
-
配置druid的相关配置
spring.datasource.druid.*
-
如果需要定制扩展,需要集成
FilterEventAdapter
,之后在数据源配置的地方配置一下即可。 -
引入以来的时候排除掉Hikali依赖,
<exclusions>
4、Spring-jdbc包
spring-jdbc包是Spring framework中一直存在的一个包,是一个ORM框架,封装了对数据库的操作。
- core,JdbcTemplate等相关核心接口和类
- datasource,数据源相关的辅助类
- object,将基本的JDBC操作封装成对象
- support错误码等其他辅助工具。
5、Spring的事务抽象
spring提供了一直的数据模型。
spring实现事务抽象中两个最重要的概念
- PlatformTransactionManager,这个内部集成了Datasoutce,hibernate,Jta等事务管理。
- TranscationDefinition 定义事务的传播特性,隔离性,超时设置,是否只读等。
事务的传播特性共有七种
- PROPAGATION.REQUEST 当前事务就使用当前的没有就用新的
- PROPAGATION.SUPPORT 事务可有可无,不是必须的
- PROPAGATION.MANDATORY 当前一定要有事务,不然就会报出异常
- PROPAGATION.REQUIRES.NEW 无论是否有事务,都启动一个新的事务
- PROPAGATION.NOT_SUPPORT 不支持事务,按照非事务的方式去运行
- PROPAGATION.NEVER 不支持事务发现事务则抛出异常
- PROPAGATION.NESTED 当前有事务就在当前事务中在启动一个事务
事务的隔离性和数据库保持一致,共有四种
开启事务注解,@EnableTransctionManagerment
,使用注解 @Transctional
6、Spring-jdbc异常抽象
spring会将常见的数据库异常转换成自己的异常,DataAccessExcception
ErrorCode定义在sql-error-code.xml定义各个数据库的异常错误码,也可以自定义覆盖。