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: 毕竟,霜星酱水平有限,如果发现任何错误还请及时邮箱告知我,我会去修改哦!