SpringBoot 数据访问

SpringBoot 数据访问

Time:2021-2-25

关于使用SpringBoot访问数据库的学习笔记。

前言

在经历了一天的折磨,被jdbc玩得团团转,群里大神各路高招,终究发现是我太年轻了,居然是版本问题下访问MySQL的URL需要一些规范导致的。各种查资料,不断偏离正确道路,直到最终别人偶然说道URL,让我恍然大悟,去看了下之前Eclipse中使用JDBC的笔记,才发现没有了关于时区设置的规范,终于SpringBoot启动没有错误了…

Author:雾雨霜星
欢迎来我的网站学习:
https://www.shuangxing.top/#/passage?id=1

转载请注明出处!!!

JDBC访问数据库

1、Mavan引入相关依赖(Jdbc):

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
            <scope>runtime</scope>
        </dependency>

注意自己使用的MySQL数据库的版本,不配置mysql依赖,SpringBoot默认使用8.0.22版本的。

jdbc的使用都是需要专门的数据库的connector,这里是mysql-connector-java。

2、配置数据源:

主要是设置数据库用户名、数据库密码、数据库的URL、数据库驱动。

修改数据源相关的配置:spring.datasource

//在 application.properties 文件中配置
spring.datasource.url=jdbc:mysql://localhost:3306/student?useSSL=false&characterEncoding=utf-8&serverTimezone = GMT
spring.datasource.username=root
spring.datasource.password=qsj225688
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

注意,URL中要加入时区设置,其次是driver-class-name,版本8的是com.mysql.cj.jdbc.Driver,版本5是com.mysql.jdbc.Driver。

似乎版本5的com.mysql.jdbc.Driver配置已经默认被springboot抛弃,建议所有都采用com.mysql.cj.jdbc.Driver。

原理:从外部库文件中找到SpringBoot自动配置相关文件,在里面有jdbc文件夹,文件夹中有关于JdbcTemplate的自动配置,该自动配置会自动配置数据源,默认使用数据源连接池:HikariDataSource。

//JdbcTemplate自动配置的类文件
// org/springframework/boot/autoconfigure/jdbc/JdbcTemplateConfiguration.class
@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnMissingBean({JdbcOperations.class})
class JdbcTemplateConfiguration {
    JdbcTemplateConfiguration() {
    }

    @Bean
    @Primary
    JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        Template template = properties.getTemplate();
        jdbcTemplate.setFetchSize(template.getFetchSize());
        jdbcTemplate.setMaxRows(template.getMaxRows());
        if (template.getQueryTimeout() != null) {
            jdbcTemplate.setQueryTimeout((int)template.getQueryTimeout().getSeconds());
        }

        return jdbcTemplate;
    }
}

可见在自动配置的时候就已经使用@Bean注解在容器中加入了JdbcTemplate。

在代码中可见,首先执行JdbcTemplate对象的初始化,使用datasource进行初始化,而这个正是数据源,DataSource dataSource。

如果数据源配置中存在问题,那么数据源连接是就会出错,容器中不会有JdbcTemplate。具体可能是因为出现了JdbcOperations类,导致后边自动配置没有执行,所以容器中就没有注册jdbcTemplate。查看源码还未找到JdbcOperations类生成的位置,有待探寻。

3、增删改查:

在SpringBoot中使用jdbc进行CRUD基本操作,可以使用***MyBatis***整合的方案,也可以直接使用SpringBoot默认提供的***JdbcTemplate***。

首先需要获取到注册的JdbcTemplate,到类的属性中。然后使用其queryForList方法执行SQL语句进行数据库操作,把查询结果保存到类型为List<Map<String, Object>>的变量中,该类型的意思是,一个列表List,其中的键值类型是String为键类型,对象(Object)为值类型。这是因为关系型数据库一般是以某一列项为主键,其余的都是对应主键的值,这样去看就不难理解为什么要使用这样的类型变量了。

参考代码如下:

//控制器设置处理方法进行数据库查询
package com.helloworld.boot.controller;

import com.helloworld.boot.userthing.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping(path = "/hello", method = {RequestMethod.POST,RequestMethod.GET})
@CrossOrigin(origins = "*")
public class MainController {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @RequestMapping(value = "/qsj/jdbc", method = RequestMethod.POST)
    @CrossOrigin(origins = "*")
    public List<Map<String, Object>> helloworld_jdbc_test(){
        String sql = "SELECT * FROM mess WHERE fight > 30";
        List<Map<String, Object>> re = jdbcTemplate.queryForList(sql);
        return re;
    }
}

直接使用@Autowired注解进行自动注入,对于查询到的结果,可以直接Return回去,SpringBoot会做好转化为字符串进行传输的工作,而前端会得到以JSON格式作为数据格式的字符串数据。

例如我直接把返回结果在前端设置到innnerHTMl中,有:

[{"number":3,"name":"托尔兹","fight":50.0,"country":"丹麦"}]

本质就是返回的List<Map<String, Object>>类型变量,此处该变量List中只有一个元素,这一个元素自身包含了四个键值对。

4、常用的JdbcTemplate方法归纳:

queryForList():
传入String参数作为SQL命令,执行SQL语句来获取数据集合。
返回的结果是一个List<Map>结构的集合。其中一个Map代表了一行数据,使用列名作为key,使用值作为value。

update():
更新数据库,主要负增加、删除、修改的工作。
传入第一个参数是String类型的SQL语句,第二个参数是SQL语句中使用占位符对象传入的参数。
例如:
int data_id = 5;
String sql = "delete from user where id=?";
jdbcTemplate.update(sql, data_id);

queryForMap():
传入String参数作为SQL命令,查询一条数据的时候使用的封装。
将列名作为key,值作为value。封装成一个map返回结果。

queryForInt()/queryForLong():
主要是为了获取数据库中记录总数,获取指定条件的记录数等,不需要对应列名,只需要返回一个数据即可。

queryForObject():
传入三个参数,第一个参数是String类型的SQL命令,第二个参数是指定接收返回数据的数据类型。
MyBatis 基本使用

MyBatis:是一个优秀的持久层框架。简化了以往采用JDBC进行数据访问的工作,可以在SpringBoot项目中高效处理数据库。

具体可以参考:

  • MyBatis官网:https://mybatis.org/mybatis-3/zh/index.html

  • MyBatis构建(Spring项目):https://mybatis.org/mybatis-3/zh/getting-started.html

  • MyBatis可选配置属性:https://mybatis.org/mybatis-3/zh/configuration.html#properties

1、整合MyBatis:

  • 引入依赖:

            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.4</version>
            </dependency>
    

    MyBatis是第三方的依赖包,其具体的项目地址可以在GitHub上找到。

    引入依赖后,在IDEA右侧栏打开Mavan控制台,可以看Dependencies内有MyBatis的包,里面有相应的自启动包。

    启动项目,项目启动成功,可以看到控制台输出日志WARN,No MyBatis mapper was found in ‘[com.helloworld.boot]’ package. Please check your configuration.这是因为我们还没有配置MyBatis的接口,而依赖引入成功,MyBatis自启动时会检查这些接口。

  • 建立MyBati全局配置文件:

    • 在src/main/resources目录下建立一个MyBatis目录,里面建立一个mybatis-config.xml的文件

    • 把官方文档中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>
          
      </configuration>
      

      注意我把configuration标签内的内容全部删去是因为我们配置SpringBoot的数据源的时候里面的东西全部都已配置好。

    • 在SpringBoot的全局配置文件中指定MyBatis的配置文件位值:

      在application.properties文件中写入:

      mybatis.check-config-location=true
      mybatis.config-location=classpath:MyBatis/mybatis-config.xml
      
  • 建立MyBatis接口映射文件:

    • src/main/resources中,在前面建立的MyBatis目录下,里面建立一个mapper的文件夹,该文件夹里面就放置相应的映射文件。

    • 在application.properties文件中写入:

      mybatis.mapper-locations=classpath:MyBatis/mapper/*.xml
      

      表示该路径文件夹内所有的xml文件都是MyBatis的映射文件。

2、MyBatis使用方法(配置模式):

​ 建立一个用于访问数据库的接口,该接口一般可以使用映射文件配置方法进行映射。

​ 假如现在数据库中有一个mess表,记录了学生的信息,包括number、name、fight、country字段,使用MyBatis进行访问。

  • 首先建立一个JavaBean有用于表示该数据库中每一条数据的实例,在主控制器文件夹的路径下建立一个bean文件夹用于存放bean,其中建立一个java类,使用@Data注解,设置其私有属性有number、name、fight、country。

  • 然后在bean文件夹所在路径下建立一个mybatismapper文件夹用于存放MyBatis的映射接口,建立接口stu,里面写入一个返回student类型的getstu方法,然后根据建立的接口来写入映射文件,例如:

    ```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="com.helloworld.boot.mybatisinterface.stu">
        <select id="getstu" resultType="com.helloworld.boot.bean.student">
            SELECT * FROM mess where number=#{number}
        </select>
    </mapper>
    ```
    
    在mapper标签中,namespace是对应的实现操作数据库的接口的位置。
    
    其中select标签标示我要执行SELECT的操作,id是方法名,resultType是返回数据类型对应的类的位置,标签内填入SQL语句,使用#{...}代表方法传入的参数。
    
  • 然后在主控制器文件夹所在目录路径下建立service文件夹,里面用于建立实现服务的类,建立StudentService类,该类用于调用接口实现数据库的操作,例如:

      package com.helloworld.boot.service;
      
      import com.helloworld.boot.bean.student;
      import com.helloworld.boot.mybatisinterface.stu;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      @Service
      public class StudentService {
          @Autowired
          stu StuService;
      
          public student getstubuNumber(int number){
              return StuService.getstu(number);
          }
      }
    

    注意需要标注service标签,那么该类就会作为服务组件,即服务层的组件,注册到容器中。

  • 接着在控制器中注入服务组件,编写相应的方法,方法中调用该服务类进行操作即可。

          package com.helloworld.boot.controller;
          
          import com.helloworld.boot.bean.student;
          import com.helloworld.boot.service.StudentService;
          import com.helloworld.boot.userthing.User;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.web.bind.annotation.*;
          
          import java.util.List;
          import java.util.Map;
          
          @RestController
          @RequestMapping(path = "/hello", method = {RequestMethod.POST,RequestMethod.GET})
          @CrossOrigin(origins = "*")
          public class MainController {
              @Autowired
              StudentService studentService;
          
              @RequestMapping(value = "/mybatis", method = RequestMethod.POST)
              @CrossOrigin(origins = "*")
              public student helloworld_MyBatis_test(@RequestParam("number") int number){
                  System.out.println("OK");
                  return studentService.getstubuNumber(number);
              }
          }
    

    需要注意的是,如果确定要传入参数的,那么记得要把参数传入。

    同理直接return结果即可,SpringBoot相应会在后续中完成传输数据格式的转化,而前端接收直接输出字符串就行,例如得到结果如下:

      {"number":1,"name":"阿谢拉特","fight":20.5,"country":"威尔士"}
    
  • 总结:MyBatis - 配置模式 使用方法:

    1.建立mybatis-config.xml全局配置文件。模板如下:

    <?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></configuration>
    

    在SpringBoot全局配置文件中定位MyBatis配置文件和映射文件的位置:

    mybatis.check-config-location=true
    mybatis.config-location=classpath:MyBatis/mybatis-config.xml
    mybatis.mapper-locations=classpath:MyBatis/mapper/*.xml
    

    2.建立JavaBean风格的Java类作为数据库的实例(数据库中每个自动对应一个私有属性),注意命名格式,若未开启驼峰命名识别属性,最好与数据库中的字段同名。

    3.建立访问数据库的接口,使用Mapper注解。接口中建立方法,每个方法对应一句SQL语句。

    4.建立对应数据库表接口的映射文件,该文件模板为:

    <?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="访问数据库的接口具体名字">
     <select id="方法名" resultType="返回类型的类的具体名">
         SQL语句
     </select>
     <insert  ...>
         ...
     </insert>
    </mapper>
    

    5.建立具体访问数据库的服务类,使用@Service注解。在服务类中自动注入访问数据库的接口(IDEA会检查报错不用理会),通过调用接口的方法实现SQL语句的执行。

    6.对于返回的数据实例,直接保存在相应的JavaBean中,直接return回去前端即可。

    MyBatis注解模式使用
  • 注解模式下,可以不建立MyBatis全局配置文件和映射文件。

  • 建立JavaBean作为数据库实例。

  • 直接建立访问数据库的接口,即Mapper接口,使用Mapper注解,在接口方法上使用@select(SQL语句)、@insert(…)等注解来确定接口中方法对应的SQL语句。例如:

    //作为数据库实例的JavaBean
    package com.helloworld.boot.bean;
    import lombok.Data;
    @Data
    public class student {
        private Long number;
        private String name;
        private double fight;
        private String country;
    }
    
    //用于访问数据库的Mapper接口
    package com.helloworld.boot.mybatisinterface;
    import com.helloworld.boot.bean.student;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Select;
    import java.util.List;
    @Mapper
    public interface stu {
        public student getstu(int number);
        @Select("SELECT * FROM mess")
        public List<student> getstuall();
    }
    
    //用于实现具体访问数据库服务的服务类
    package com.helloworld.boot.service;
    import com.helloworld.boot.bean.student;
    import com.helloworld.boot.mybatisinterface.stu;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import java.util.List;
    @Service
    public class StudentService {
        @Autowired
        stu StuService;
        public student getstubuNumber(int number){
            return StuService.getstu(number);
        }
        public List<student> getstudentall(){return StuService.getstuall();}
    }
    
    //主控制器
    package com.helloworld.boot.controller;
    import com.helloworld.boot.bean.student;
    import com.helloworld.boot.service.StudentService;
    import com.helloworld.boot.userthing.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.web.bind.annotation.*;
    import java.util.List;
    import java.util.Map;
    @RestController
    @RequestMapping(path = "/hello", method = {RequestMethod.POST,RequestMethod.GET})
    @CrossOrigin(origins = "*")
    public class MainController {
        @Autowired
        private JdbcTemplate jdbcTemplate;
        @Autowired
        StudentService studentService;
        @RequestMapping(value = "/mybatis2", method = RequestMethod.POST)
        @CrossOrigin(origins = "*")
        public List<student> helloworld_MyBatis_test_2(){
            System.out.println("OK");
            return studentService.getstudentall();
        }
    }
    
  • 使用@Option注解完成对具体执行的属性进行设置,即标签中的属性项。例如使用Insert指令时,可以设置属性,使用自增的组件,对应自增的字段为某个字段,即设置useGenerateKeys=“true”,KeyProperty=“id”。

  • 若需要配置MyBatis属性,可以在application.properties文件中写入mybatis.configuration前缀的键来进行配置。

    注意若使用了application.properties文件配置mybatis属性(不是指定配置文件位置),就不可以再使用配置文件位置指定。

  • 建议采用MyBatis独立的全局配置文件,而使用注解代替映射文件。

MyBatis驼峰命名识别

配置MyBatis属性,mapUnderscoreToCamelCase,设置为true时,开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。

可以在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>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>

可以选择在application.properties文件中配置:

mybatis.configuration.map-underscore-to-camel-case=true

以此例子展示如何配置MyBatis属性,具体属性表可以参考MyBatis官网中xml配置内的属性。

MyBatis访问数据库的一些问题

最终发现,如果我的数据库表的字段名字中带有下划线( _ )的时候,读取得到的数据一定会是null,因此要注意,名字最好不要带下划线。

似乎不是驼峰命名法设置带来的问题,无论我关闭还是开启,这个问题似乎都是在的。

在此记录。

转载请注明出处!!!
Author:雾雨霜星
欢迎来我的网站学习:
https://www.shuangxing.top/#/passage?id=1

Thanks!

PS: 毕竟,霜星酱水平有限,如果发现任何错误还请及时邮箱告知我,我会去修改哦!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值