Spring操作数据库

2019/05/12 框架

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

从这里可以看出以下内容

  1. pom文件
  2. main类,springboot项目的入口类
  3. test类
  4. 其他的,比如.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生成的这个项目里面有以下几个内容

  1. 定义java版本
  2. 正确的引入了 actuator,h2,jdbc等依赖。
  3. 使用了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为我们做了那些事情

  1. 通过DataSourceAutoConfiguration 为我们配置了数据源
  2. 通过DataSourceTransactionManagerAutoConfiguration为我们配置了数据源的事务管理
  3. 通过JdbcTemplateAutoConfiguration为我们配置了JdbcTemplate
  4. 以上只有当符合条件的时候才会去自动配置、

2、配置多个数据源

  1. 将两个数据源的配置分开。
  2. 告知系统需要去操作哪一个数据源。
  3. @Primary 作为主要bean。
  4. 自己在代码中控制 DataSourceAutoConfiguration,DataSourceTransctionManagerAutoConfiguration,JdbcTemplateAutoConfiguration失效(在springbootApplication中加入exclude),自己来完成这三个的bean创建(使用@Bean)。

3、数据库连接池

3.1、hikaliCP

​ HiukaliCP来自于日语,意思是光,就是快的意思。具体内容可以参考http://brettwooldridge.github.io/HikariCP/

​ 为什么那么快?

  1. 字节码级别的优化 (很多方法都是通过JavaAssist生成)

  2. 大量的一些小的改动

    1. 用自己封装的一个FastStatementList代替了Arraylist
    2. 无锁的集合ConcurrentBag
    3. 代理类的优化

    在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应用应为。

    主要功能项

    1. 详细的监控
    2. ExceptionSorter针对主流数据库的返回码都有支持
    3. SQL防注入
    4. 内置的加密配置
    5. 众多的扩展点,方便进行定制。

    如何使用

    1. 引入pom

      <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.1.19</version>
      </dependency>
      
    2. 配置druid的相关配置

      spring.datasource.druid.*
      
    3. 如果需要定制扩展,需要集成FilterEventAdapter,之后在数据源配置的地方配置一下即可。

    4. 引入以来的时候排除掉Hikali依赖,<exclusions>

4、Spring-jdbc包

​ spring-jdbc包是Spring framework中一直存在的一个包,是一个ORM框架,封装了对数据库的操作。

  1. core,JdbcTemplate等相关核心接口和类
  2. datasource,数据源相关的辅助类
  3. object,将基本的JDBC操作封装成对象
  4. support错误码等其他辅助工具。

5、Spring的事务抽象

​ spring提供了一直的数据模型。

​ spring实现事务抽象中两个最重要的概念

  1. PlatformTransactionManager,这个内部集成了Datasoutce,hibernate,Jta等事务管理。
  2. TranscationDefinition 定义事务的传播特性,隔离性,超时设置,是否只读等。

事务的传播特性共有七种

  1. PROPAGATION.REQUEST 当前事务就使用当前的没有就用新的
  2. PROPAGATION.SUPPORT 事务可有可无,不是必须的
  3. PROPAGATION.MANDATORY 当前一定要有事务,不然就会报出异常
  4. PROPAGATION.REQUIRES.NEW 无论是否有事务,都启动一个新的事务
  5. PROPAGATION.NOT_SUPPORT 不支持事务,按照非事务的方式去运行
  6. PROPAGATION.NEVER 不支持事务发现事务则抛出异常
  7. PROPAGATION.NESTED 当前有事务就在当前事务中在启动一个事务

事务的隔离性和数据库保持一致,共有四种

开启事务注解,@EnableTransctionManagerment,使用注解 @Transctional

6、Spring-jdbc异常抽象

​ spring会将常见的数据库异常转换成自己的异常,DataAccessExcception

ErrorCode定义在sql-error-code.xml定义各个数据库的异常错误码,也可以自定义覆盖。

Search

    欢迎添加我的个人微信号

    个人微信哦

    Table of Contents