SpringBoot1.x之数据访问
Posted xuweiweiwoaini
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot1.x之数据访问相关的知识,希望对你有一定的参考价值。
1 简介
- 对于数据访问层,无论是SQL还是NOSQL,SpringBoot默认采用整合SpringData的方式进行统一处理,添加大量自动配置,屏蔽了很多细节设置。引入了各种xxxTemplate,xxxRepository来简化我们对数据访问层的操作。
2 整合基本JDBC和数据源
2.1 JDBC
2.1.1 导入依赖的jar包
<!-- SpringBoot的web模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- SpringBoot的web模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
2.1.2 application.yml配置
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://47.103.20.129:3306/jdbc
2.1.3 测试
- 示例:
package com.sunxiaping.restful; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.sql.DataSource; import java.sql.SQLException; @RunWith(SpringRunner.class) @SpringBootTest public class RestfulApplicationTest { @Autowired private DataSource dataSource; @Test public void test() throws SQLException { System.out.println(dataSource.getClass()); //org.apache.tomcat.jdbc.pool.DataSource System.out.println(dataSource.getConnection()); } }
- 效果:
- 默认是用org.apache.tomcat.jdbc.pool.DataSource作为数据源的。
- 数据源的相关配置都是在DataSourceProperties里面。
- 自动配置原理:
- ①参考DataSourceConfiguration,根据配置创建数据源,默认使用的是Tomcat的连接池,当然可以使用spring.datasource.type指定自定义的数据源类型。其源码如下:
package org.springframework.boot.autoconfigure.jdbc; abstract class DataSourceConfiguration { /** * Tomcat Pool DataSource configuration. */ @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true) static class Tomcat extends DataSourceConfiguration { @Bean @ConfigurationProperties(prefix = "spring.datasource.tomcat") public org.apache.tomcat.jdbc.pool.DataSource dataSource( DataSourceProperties properties) { org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource( properties, org.apache.tomcat.jdbc.pool.DataSource.class); DatabaseDriver databaseDriver = DatabaseDriver .fromJdbcUrl(properties.determineUrl()); String validationQuery = databaseDriver.getValidationQuery(); if (validationQuery != null) { dataSource.setTestOnBorrow(true); dataSource.setValidationQuery(validationQuery); } return dataSource; } } }
- ②SpringBoot默认支持的数据源:
org.apache.tomcat.jdbc.pool.DataSource、HikariDataSource、org.apache.commons.dbcp.BasicDataSource
- ③自定义数据源类型:
package org.springframework.boot.autoconfigure.jdbc; abstract class DataSourceConfiguration { /** * Generic DataSource configuration. */ @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type") static class Generic { @Bean public DataSource dataSource(DataSourceProperties properties) { //使用DataSourceProperties创建数据源,利用反射创建相应type类型的数据源,并绑定相关属性 return properties.initializeDataSourceBuilder().build(); } } }
- ④在DataSourceAutoConfiguration注册了DataSourceInitializer这个组件,其源码如下:
package org.springframework.boot.autoconfigure.jdbc; @Configuration @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) @EnableConfigurationProperties({DataSourceProperties.class}) @Import({Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class}) public class DataSourceAutoConfiguration { @Bean @ConditionalOnMissingBean public DataSourceInitializer dataSourceInitializer(DataSourceProperties properties, ApplicationContext applicationContext) { return new DataSourceInitializer(properties, applicationContext); } }
- 而DataSourceInitializer的源码如下:
package org.springframework.boot.autoconfigure.jdbc; /** * Bean to handle {@link DataSource} initialization by running {@literal schema-*.sql} on * {@link PostConstruct} and {@literal data-*.sql} SQL scripts on a * {@link DataSourceInitializedEvent}. * * @author Dave Syer * @author Phillip Webb * @author Eddú Meléndez * @author Stephane Nicoll * @author Kazuki Shimizu * @since 1.1.0 * @see DataSourceAutoConfiguration */ class DataSourceInitializer implements ApplicationListener<DataSourceInitializedEvent> { }
- 从中我们可以知道DataSourceInitializer就是ApplicationListener,其作用:
- 1. runSchemaScripts();运行建表语句。
- 2. runDataScripts();运行插入数据语句。
schema‐*.sql、data‐*.sql
默认规则:schema.sql,schema‐all.sql;
spring: datasource: # 建表语句 schema: - classpath:employee.sql - classpath:department.sql # 插入数据语句 data: - classpath:schema-employee-data.sql
- ⑤SpringBoot默认自动配置了JdbcTemplate来操作数据库。
package org.springframework.boot.autoconfigure.jdbc; @Configuration @ConditionalOnClass({DataSource.class, JdbcTemplate.class}) @ConditionalOnSingleCandidate(DataSource.class) @AutoConfigureAfter({DataSourceAutoConfiguration.class}) public class JdbcTemplateAutoConfiguration { private final DataSource dataSource; public JdbcTemplateAutoConfiguration(DataSource dataSource) { this.dataSource = dataSource; } @Bean @Primary @ConditionalOnMissingBean({JdbcOperations.class}) public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(this.dataSource); } @Bean @Primary @ConditionalOnMissingBean({NamedParameterJdbcOperations.class}) public NamedParameterJdbcTemplate namedParameterJdbcTemplate() { return new NamedParameterJdbcTemplate(this.dataSource); } }
2.2 整合Druid数据源
2.2.1 导入依赖的jar包
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency>
2.2.2 配置application.yml
spring: datasource: driver-class-name: com.mysql.jdbc.Driver username: root password: 123456 url: jdbc:mysql://47.103.20.129:3306/jdbc?characterEncoding=utf-8&useSSL=false #指定Druid数据源 type: com.alibaba.druid.pool.DruidDataSource # 数据源其他配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,‘wall‘用于防火墙 filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
2.2.3 DruidConfig.java
- 示例:
package com.sunxiaping.restful.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @Configuration public class DruidConfig { @ConfigurationProperties(prefix = "spring.dataSource") @Bean public DataSource dataSource(){ return new DruidDataSource(); } //配置Druid的监控 //1.配置一个管理后台的Servlet @Bean public ServletRegistrationBean servletRegistrationBean(){ ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*"); Map<String,String> map = new HashMap<>(); map.put("loginUsername", "admin"); map.put("loginPassword", "123456"); map.put("allow", "");//默认就是允许所有访问 // map.put("deny", "192.168.15.21"); 拒绝谁访问 servletRegistrationBean.setInitParameters(map); return servletRegistrationBean; } //2.配置一个监控的filter @Bean public FilterRegistrationBean filterRegistrationBean(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new WebStatFilter()); Map<String,String> initParams = new HashMap<>(); initParams.put("exclusions","*.js,*.css,/druid/*"); filterRegistrationBean.setInitParameters(initParams); filterRegistrationBean.setUrlPatterns(Arrays.asList("/*")); return filterRegistrationBean; } }
3 SpringBoot整合Mybatis
3.1 基础环境搭建
- pom.xml
<!-- SpringBoot的web模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.1</version> </dependency>
- application.yml
spring: datasource: driver-class-name: com.mysql.jdbc.Driver username: root password: 123456 url: jdbc:mysql://47.103.20.129:3306/jdbc?characterEncoding=utf-8&useSSL=false #指定Druid数据源 type: com.alibaba.druid.pool.DruidDataSource # 数据源其他配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,‘wall‘用于防火墙 filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
- DruidConfig.java
package com.sunxiaping.restful.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @Configuration public class DruidConfig { @ConfigurationProperties(prefix = "spring.dataSource") @Bean public DataSource dataSource(){ return new DruidDataSource(); } //配置Druid的监控 //1.配置一个管理后台的Servlet @Bean public ServletRegistrationBean servletRegistrationBean(){ ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*"); Map<String,String> map = new HashMap<>(); map.put("loginUsername", "admin"); map.put("loginPassword", "123456"); map.put("allow", "");//默认就是允许所有访问 // map.put("deny", "192.168.15.21"); 拒绝谁访问 servletRegistrationBean.setInitParameters(map); return servletRegistrationBean; } //2.配置一个监控的filter @Bean public FilterRegistrationBean filterRegistrationBean(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new WebStatFilter()); Map<String,String> initParams = new HashMap<>(); initParams.put("exclusions","*.js,*.css,/druid/*"); filterRegistrationBean.setInitParameters(initParams); filterRegistrationBean.setUrlPatterns(Arrays.asList("/*")); return filterRegistrationBean; } }
- 建表语句文件:
/* Navicat MySQL Data Transfer Source Server : 本地 Source Server Version : 50528 Source Host : 127.0.0.1:3306 Source Database : restful_crud Target Server Type : MYSQL Target Server Version : 50528 File Encoding : 65001 Date: 2018-03-05 10:41:40 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for department -- ---------------------------- DROP TABLE IF EXISTS `department`; CREATE TABLE `department` ( `id` int(11) NOT NULL AUTO_INCREMENT, `departmentName` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
/* Navicat MySQL Data Transfer Source Server : 本地 Source Server Version : 50528 Source Host : 127.0.0.1:3306 Source Database : restful_crud Target Server Type : MYSQL Target Server Version : 50528 File Encoding : 65001 Date: 2018-03-05 10:41:58 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for employee -- ---------------------------- DROP TABLE IF EXISTS `employee`; CREATE TABLE `employee` ( `id` int(11) NOT NULL AUTO_INCREMENT, `lastName` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `gender` int(2) DEFAULT NULL, `d_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
- 创建JavaBean:
- Employee.java
package com.sunxiaping.restful.bean; public class Employee { private Integer id; private String lastName; private Integer gender; private String email; private Integer dId; public void setId(Integer id) { this.id = id; } public void setLastName(String lastName) { this.lastName = lastName; } public void setGender(Integer gender) { this.gender = gender; } public void setEmail(String email) { this.email = email; } public void setdId(Integer dId) { this.dId = dId; } public Integer getId() { return id; } public String getLastName() { return lastName; } public Integer getGender() { return gender; } public String getEmail() { return email; } public Integer getdId() { return dId; } }
- Department.java
package com.sunxiaping.restful.bean; public class Department { private Integer id; private String departmentName; public void setId(Integer id) { this.id = id; } public void setDepartmentName(String departmentName) { this.departmentName = departmentName; } public Integer getId() { return id; } public String getDepartmentName() { return departmentName; } }
3.2 注解版
- 示例:
package com.sunxiaping.restful.mapper; import com.sunxiaping.restful.entities.Department; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Select; @Mapper //指定这是一个操作数据库的Mapper public interface EmployeeMapper { @Select("select * from department where id = #{id}") Department getDeptById(Integer id); @Options(useGeneratedKeys = true,keyProperty = "id") @Insert("insert into department(departmentName) values (#{departmentName)") int insertDept(Department department); }
- 如果需要自定义Mybatis配置规则,则需要给容器中添加一个ConfigurationCustomizer的组件:
package com.sunxiaping.restful.config; import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer; import org.springframework.context.annotation.Configuration; @Configuration public class MybatisConfig { public ConfigurationCustomizer configurationCustomizer(){ return new ConfigurationCustomizer() { @Override public void customize(org.apache.ibatis.session.Configuration configuration) { //开启驼峰命名 configuration.setMapUnderscoreToCamelCase(true); } }; } }
- 如果不想在Mapper接口上加@Mapper接口,那么可以在配置类上加上@MapperScan注解即可。
package com.sunxiaping.restful; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; //使用@MapperScan批量扫描所有的Mapper接口 @MapperScan(value = "com.sunxiaping.restful.mapper") @SpringBootApplication public class RestfulApplication { public static void main(String[] args) { SpringApplication.run(RestfulApplication.class, args); } }
3.3 配置版
xx
以上是关于SpringBoot1.x之数据访问的主要内容,如果未能解决你的问题,请参考以下文章