springBoot数据访问

前言

上一篇:Spring Boot Web

下一篇:启动配置原理

一、Docker

1、简介

Docker是一个开源的应用容器引擎;是一个轻量级容器技术;Docker支持将软件编译成一个镜像;然后在镜像中各种软件做好配置,将镜像发布出去,其他使用者可以直接使用这个镜像;运行中的这个镜像称为容器,容器启动是非常快速的。

Docker架构

在这里插入图片描述

2、核心概念

2.1 概念

docker主机(Host):安装了Docker程序的机器(Docker直接安装在操作系统之上);

docker客户端(Client):连接docker主机进行操作;

docker仓库(Registry):用来保存各种打包好的软件镜像;

docker镜像(Images):软件打包好的镜像;放在docker仓库中;

docker容器(Container):镜像启动后的实例称为一个容器;容器是独立运行的一个或一组应用
在这里插入图片描述

2.2 使用Docker的步骤:

1)、安装Docker

2)、去Docker仓库找到这个软件对应的镜像;

3)、使用Docker运行这个镜像,这个镜像就会生成一个Docker容器;

4)、对容器的启动停止就是对软件的启动停止;

3、安装Docker

3.1 安装Linux并配置好客户端

​ 1)、VMWare、VirtualBox(安装);

​ 2)、导入虚拟机文件centos7-atguigu.ova;

​ 3)、双击启动linux虚拟机;使用 root/ 123456登陆

​ 4)、使用客户端连接linux服务器进行命令操作;

​ 5)、设置虚拟机网络;

​ 桥接网络=选好网卡==接入网线;

​ 6)、设置好网络以后使用命令重启虚拟机的网络

service network restart

​ 7)、查看linux的ip地址

ip addr

​ 8)、使用客户端连接linux;

3.2 安装Docker(CentOS)

  • 安装docker: yum install docker
  • 在安装过程中输入:y 确认安装
  • 启动docker:
[root@localhost ~]# systemctl start docker
查看版本
[root@localhost ~]# docker -v      
Docker version 1.12.6, build 3e8e77d/1.12.6
  • 设置开机自启动
[root@localhost ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
  • 停止docker
systemctl stop docker

4、常用命令与操作

4.1 镜像操作

操作命令说明
检索docker search 关键字 eg:docker search redis我们经常去docker hub上检索镜像的详细信息,如镜像的TAG。
拉取docker pull 镜像名:tag:tag是可选的,tag表示标签,多为软件的版本,默认是latest
列表docker images查看所有本地镜像
删除docker rmi image-id删除指定的本地镜像

4.2 容器操作

  • 搜索镜像: docker search tomcat
  • 拉取镜像:docker pull tomcat
  • 根据镜像启动容器: docker run --name mytomcat -d tomcat:latest
  • 查看运行中的容器:docker ps
  • 停止运行中的容器
  • 查看所有容器:docker ps -a
  • 删除一个容器:docker rm 容器id
  • 启动容器: docker start 容器id
  • 查看日志:docker logs container-name/container-id

二、SpringBoot数据访问

1、JDBC

1.1 引入JDBC依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jdbc</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-web</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.22</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

1.2 配置DataSource

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.0.103:3306/jdbc
    driver-class-name: com.mysql.cj.jdbc.Driver
    #spring.datasource.initialization-mode  初始化模式(springboot2.0),其中有三个值,always为始终执行初始化,embedded只初始化内存数据库(默认值),如h2等,never为不执行初始化。
    initialization-mode: always

1.3 连接测试

@SpringBootTest
class JdbcApplicationTests {
	@Autowired
	DataSource dataSource;
	@Test
	void contextLoads() throws SQLException {
		System.out.println(dataSource.getClass());
		Connection conn = dataSource.getConnection();
		System.out.println(conn);
		conn.close();
	}
}

1.4 自动配置原理

  • Spring Boot对于JDBC的配置都在:org.springframework.boot.autoconfigure.jdbc下。

  • DataSourceConfiguration类中定义了springBoot支持的数据源:

    • DBCP:org.apache.commons.dbcp2.BasicDataSource
    • Hikari:com.zaxxer.hikari.HikariDataSource
    • tomcat JDBC:org.apache.tomcat.jdbc.pool.DataSource
    • 自定义连接池:
    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnMissingBean({DataSource.class})
    @ConditionalOnProperty(
        name = {"spring.datasource.type"}
    )
    static class Generic {
        Generic() {
        }
    
        @Bean
        DataSource dataSource(DataSourceProperties properties) {
            //使用DataSourceBuilder创建数据源,利用反射创建响应type的数据源,并且绑定相关属性
            return properties.initializeDataSourceBuilder().build();
        }
    }
    
  • DataSourceAutoConfiguration类中自动导入了 DataSourceInitializationConfiguration类,而该类又自动导入了 DataSourceInitializerInvoker类,在该类中有如下两个方法:

public void afterPropertiesSet() {
    DataSourceInitializer initializer = this.getDataSourceInitializer();
    if (initializer != null) {
        boolean schemaCreated = this.dataSourceInitializer.createSchema();
        if (schemaCreated) {
            this.initialize(initializer);
        }
    }
}
private void initialize(DataSourceInitializer initializer) {
    try {
        this.applicationContext.publishEvent(new DataSourceSchemaCreatedEvent(initializer.getDataSource()));
        if (!this.initialized) {
            this.dataSourceInitializer.initSchema();
            this.initialized = true;
        }
    } catch (IllegalStateException var3) {
        logger.warn(LogMessage.format("Could not send event to complete DataSource initialization (%s)", var3.getMessage()));
    }
}
  • 在这两个方法中分别调用了如下方法:
boolean schemaCreated = this.dataSourceInitializer.createSchema();
this.dataSourceInitializer.initSchema();
  • 这两个方法如下:
boolean createSchema() {
    List<Resource> scripts = this.getScripts("spring.datasource.schema", this.properties.getSchema(), "schema");
    if (!scripts.isEmpty()) {
        if (!this.isEnabled()) {
            logger.debug("Initialization disabled (not running DDL scripts)");
            return false;
        }
        String username = this.properties.getSchemaUsername();
        String password = this.properties.getSchemaPassword();
        this.runScripts(scripts, username, password);
    }
    return !scripts.isEmpty();
}
void initSchema() {
    List<Resource> scripts = this.getScripts("spring.datasource.data", this.properties.getData(), "data");
    if (!scripts.isEmpty()) {
        if (!this.isEnabled()) {
            logger.debug("Initialization disabled (not running data scripts)");
            return;
        }
        String username = this.properties.getDataUsername();
        String password = this.properties.getDataPassword();
        this.runScripts(scripts, username, password);
    }
}
  • 他们均利用了 getScripts方法 :
private List<Resource> getScripts(String propertyName, List<String> resources, String fallback) {
    if (resources != null) {
        return this.getResources(propertyName, resources, true);
    } else {
        String platform = this.properties.getPlatform();
        List<String> fallbackResources = new ArrayList();
        fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
        fallbackResources.add("classpath*:" + fallback + ".sql");
        return this.getResources(propertyName, fallbackResources, false);
    }
}
  • 而从该方法可以看出可以看出,如果我们没有在配置文件中配置脚本的具体位置,就会在classpath下找.sql文件。
  • initschema()createSchema()中可以看出:
    • 创建SQL使用的是:scheam.sqlschema-all.sql
    • 初始化数据使用的是:data.sqldata-all.sql
  • 我们也可以在配置文件中自己指定位置:
spring:
  datasource:
    schema:
      - classpath:department.sql
      - 指定位置

2、整合Druid数据源

2.1 数据库连接池的选择

选择哪个数据库连接池

  • DBCP2 是 Appache 基金会下的项目,是最早出现的数据库连接池 DBCP 的第二个版本。
  • C3P0 最早出现时是作为 Hibernate 框架的默认数据库连接池而进入市场。
  • Druid 是阿里巴巴公司开源的一款数据库连接池,其特点在于有丰富的附加功能。
  • HikariCP 相较而言比较新,它最近两年才出现,据称是速度最快的数据库连接池。最近更是被 Spring 设置为默认数据库连接池。

不选择 C3P0 的原因:

  • C3P0 的 Connection 是异步释放。这个特性会导致释放的在某些情况下 Connection 实际上 still in use ,并未真正释放掉,从而导致连接池中的 Connection 耗完,等待状况。
  • Hibernate 现在对所有数据库连接池一视同仁,官方不再指定『默认』数据库连接池。因此 C3P0 就失去了『官方』光环。

不选择 DBCP2 的原因:

  • 相较于 Druid 和 HikariCP,DBCP2 没有什么特色功能/卖点。基本上属于 能用,没毛病 的情况,地位显得略有尴尬。

引用自:https://cloudlandboy.github.io/myNote/#/backend/springboot/jdbc

2.2 整合Druid

<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.22</version>
</dependency>
  • 在配置文件中指定数据源类型:

    spring:
      datasource:
        username: root
        password: root
        url: jdbc:mysql://192.168.0.103:3306/jdbc
        driver-class-name: com.mysql.cj.jdbc.Driver
        initialization-mode: always
        type: com.alibaba.druid.pool.DruidDataSource
    
  • 运行之前的测试类,查看数据源的类型。

  • 配置参数,Druid的配置参数有两种方式,一种为编写代码,另一种为配置方式,接下来分别举例

    • 编写代码:
    @Configuration
    public class MyConfig {
        @ConfigurationProperties(prefix = "spring.datasource")
        @Bean
        public DataSource dataSource(){
            return new DruidDataSource();
        }
        @Bean
        public ServletRegistrationBean statViewServlet(){
            ServletRegistrationBean<StatViewServlet> regist = new ServletRegistrationBean<StatViewServlet>(new StatViewServlet(), "/druid/*");
            Map<String,String> initMap = new HashMap<>();
            initMap.put("loginUsername","admin");
            initMap.put("loginPassword","admin");
            regist.setInitParameters(initMap);
            return regist;
        }
        @Bean
        public FilterRegistrationBean webStatFilter(){
            FilterRegistrationBean bean = new FilterRegistrationBean();
            bean.setFilter(new WebStatFilter());
            Map<String,String> initMap = new HashMap<>();
            initMap.put("exclusions","*.js,*.css,/druid/*");
            bean.setInitParameters(initMap);
            bean.setUrlPatterns(Arrays.asList("/*"));
            return bean;
        }
    }
    
    • 编写配置文件
    spring:
      datasource:
        username: root
        password: root
        url: jdbc:mysql://192.168.0.103:3306/jdbc
        driver-class-name: com.mysql.cj.jdbc.Driver
        initialization-mode: always
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
              # 连接池配置
              # 配置初始化大小、最小、最大
              initial-size: 1
              min-idle: 1
              max-active: 20
              # 配置获取连接等待超时的时间
              max-wait: 3000
              validation-query: SELECT 1 FROM DUAL
              test-on-borrow: false
              test-on-return: false
              test-while-idle: true
              pool-prepared-statements: true
              time-between-eviction-runs-millis: 60000
              min-evictable-idle-time-millis: 300000
              filters: stat,wall,slf4j
              # 配置web监控,默认配置也和下面相同(除用户名密码,enabled默认false外),其他可以不配
              web-stat-filter:
                enabled: true
                url-pattern: /*
                exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
              stat-view-servlet:
                enabled: true
                url-pattern: /druid/*
                login-username: admin
                login-password: root
                allow: 127.0.0.1
    

3、整合MyBatis

3.1 环境搭建

  • 引入依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jdbc</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-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.2</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.22</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
  • 在resources下创建department.sqlemployee.sql,项目启动时创建表

    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;
    
    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;
    
  • 创建实体类

  • 编辑配置文件

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.0.103:3306/jdbc
    driver-class-name: com.mysql.cj.jdbc.Driver
    initialization-mode: always
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
          # 连接池配置
          # 配置初始化大小、最小、最大
          initial-size: 1
          min-idle: 1
          max-active: 20
          # 配置获取连接等待超时的时间
          max-wait: 3000
          validation-query: SELECT 1 FROM DUAL
          test-on-borrow: false
          test-on-return: false
          test-while-idle: true
          pool-prepared-statements: true
          time-between-eviction-runs-millis: 60000
          min-evictable-idle-time-millis: 300000
          filters: stat,wall,slf4j
          # 配置web监控,默认配置也和下面相同(除用户名密码,enabled默认false外),其他可以不配
          web-stat-filter:
            enabled: true
            url-pattern: /*
            exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
          stat-view-servlet:
            enabled: true
            url-pattern: /druid/*
            login-username: admin
            login-password: root
            allow: 127.0.0.1
    schema:
      - classpath:department.sql
      - classpath:employee.sql
  • Mybatis环境整合有两种方式,接下来分别介绍:

    • xml方式:
    1. 创建mybatis全局配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
          <typeAliases>
              <package name="cn.clboy.springbootmybatis.model"/>
          </typeAliases>
      </configuration>
      
    2. 创建EmployeeMapper接口

      public interface EmployeeMapper {
      
          List<Employee> selectAll();
      
          int save(Employee employee);
      }
      
    3. 创建EmployeeMapper.xml映射文件

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="cn.clboy.springbootmybatis.mapper.EmployeeMapper">
          <select id="selectAll" resultType="employee">
              SELECT * FROM employee
          </select>
          <insert id="save" parameterType="employee" useGeneratedKeys="true" keyProperty="id">
             INSERT INTO employee(lastName,email,gender,d_id) VALUES (#{lastName},#{email},#{gender},#{d_id})
          </insert>
      </mapper>
      
    4. 配置文件(application.yaml)中指定配置文件和映射文件的位置

      mybatis:
        config-location: classpath:mybatis/mybatis-config.xml
        mapper-locations: classpath:mybatis/mapper/*.xmlCopy to clipboardErrorCopied
      
    5. 给表中插入两个数据,用于测试

       INSERT INTO employee(lastName,email,gender,d_id) VALUES ('张三','123456@qq.com',1,1);
       INSERT INTO employee(lastName,email,gender,d_id) VALUES ('lisi','245612@qq.com',1,1);
      
    6. 创建EmployeeController

      @RestController
      public class EmployeeController {
      
          @Autowired
          private EmployeeMapper employeeMapper;
      
          @RequestMapping("/empl/list")
          public List<Employee> getALl() {
              return employeeMapper.selectAll();
          }
      
          @RequestMapping("/empl/{id}")
          public Employee save(Employee employee) {
              employeeMapper.save(employee);
              return employee;
          }
      }
      
    • 注解方式

    1.创建 DepartmentMapper

    @Mapper
    public interface DepartmentMapper {
        @Select("select * from department")
        public List<Department> selectAll();
    
        @Select("select * from department where id = #{id}")
        public Department selectDepartment(Integer id);
    
        @Delete("delete from department where id = #{id}")
        public Integer deleteDepartment(Integer id);
    
        @Options(useGeneratedKeys = true,keyProperty = "id")
        @Insert("insert into department(department_name) values(#{departmentName})")
        public Integer insertDepartment(Department department);
    
        @Update("update department set department_name=#{departmentName} where id=#{id}")
        public Integer updateDepartment(Department department);
    }
    

    2.编写 DeptController类:

    @RestController
    public class DeptController {
    
        @Autowired
        private DepartmentMapper dept;
    
        @GetMapping("/dept/all")
        public List<Department> selectAllDept(){
            return  dept.selectAll();
        }
    
        @GetMapping("/dept/{id}")
        public Department select(@PathVariable("id") Integer id){
            return dept.selectDepartment(id);
        }
    
    
        @GetMapping("/dept")
        public Department insert(Department department){
            dept.insertDepartment(department);
            return department;
        }
    }
    

3.2 mybatis的配置

  • 开启驼峰命名法

我们的实体类和表中的列名一致,一点问题也没有,我们把department表的departmentName列名改为department_name看看会发生什么,访问:http://localhost:8080/dep/1获取数据

[{"id":1,"departmentName":null}]Copy to clipboardErrorCopied

由于列表和属性名不一致,所以就没有封装进去,我们表中的列名和实体类属性名都是遵循驼峰命名规则的,可以开启mybatis的开启驼峰命名配置

mybatis:
  configuration:
    map-underscore-to-camel-case: true

然后重启项目,重新插入数据,再查询就发现可以封装进去了,也可以通过向spring容器中注入org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer的方法设置mybatis参数

@Configuration
public class MybatisConfig {

    @Bean
    public ConfigurationCustomizer mybatisConfigurationCustomizer() {
        return new ConfigurationCustomizer() {
            @Override
            public void customize(org.apache.ibatis.session.Configuration configuration) {
                configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }
}

1574430056512

1574430280791

  • Mapper扫描

使用@mapper注解的类可以被扫描到容器中,但是每个Mapper都要加上这个注解就是一个繁琐的工作,能不能直接扫描某个包下的所有Mapper接口呢,当然可以,在springboot启动类上加上@MapperScan

@MapperScan("cn.clboy.springbootmybatis.mapper")
@SpringBootApplication
public class SpringbootMybatisApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootMybatisApplication.class, args);
    }

}

4、整合SpringData JPA

4.1 简介

在这里插入图片描述

4.2 整合SpringData JPA

  • 导入依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
  • 编写一个实体类(bean)和数据表进行映射,并且配置好映射关系;
//使用JPA注解配置映射关系
@Entity //告诉JPA这是一个实体类(和数据表映射的类)
@Table(name = "tbl_user") //@Table来指定和哪个数据表对应;如果省略默认表名就是user;
public class User {

    @Id //这是一个主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)//自增主键
    private Integer id;

    @Column(name = "last_name",length = 50) //这是和数据表对应的一个列
    private String lastName;
    @Column //省略默认列名就是属性名
    private String email;
  • 编写一个Dao接口来操作实体类对应的数据表(Repository)
//继承JpaRepository来完成对数据库的操作
public interface UserRepository extends JpaRepository<User,Integer> {
}
  • 基本的配置JpaProperties
spring:  
 jpa:
    hibernate:
#     更新或者创建数据表结构
      ddl-auto: update
#    控制台显示SQL
    show-sql: true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值