龙空技术网

Spring Boot:数据访问和视图技术

RendaZhang 227

前言:

此刻咱们对“spring数据访问层”大概比较关怀,大家都想要知道一些“spring数据访问层”的相关知识。那么小编同时在网络上收集了一些关于“spring数据访问层””的相关知识,希望看官们能喜欢,各位老铁们一起来了解一下吧!

SpringBoot 数据访问

Spring Boot 整合 MyBatis

MyBatis 是一款优秀的持久层框架,Spring Boot 官方虽然没有对 MyBatis 进行整合,但是 MyBatis 团队自行适配了对应的启动器,进一步简化了使用 MyBatis 进行数据的操作。

因为 Spring Boot 框架开发的便利性,所以实现 Spring Boot 与数据访问层框架(例如 MyBatis)的整合非常简单,主要是引入对应的依赖启动器,并进行数据库相关参数设置即可。

基础环境搭建1)数据准备

在 MySQL 中,先创建了一个数据库 springbootdata,然后创建了两个表 t_articlet_comment 并向表中插入数据。其中评论表 t_commenta_id 与文章表 t_article 的主键 id 相关联。

# 创建数据库CREATE DATABASE IF NOT EXISTS springbootdata DEFAULT CHARACTER SET utf8;# 选择使用数据库USE springbootdata;# 创建表 t_article 并插入相关数据DROP TABLE IF EXISTS t_article;CREATE TABLE t_article(    id      int(20) NOT NULL AUTO_INCREMENT COMMENT '文章id',    title   varchar(200) DEFAULT NULL COMMENT '文章标题',    content longtext COMMENT '文章内容',    PRIMARY KEY (id)) ENGINE = InnoDB AUTO_INCREMENT = 2 DEFAULT CHARSET=utf8;​INSERT INTO t_article VALUES (1, 'Spring Boot 基础入门', '从入门到精通讲解...');INSERT INTO t_article VALUES (2, 'Spring Cloud 基础入门', '从入门到精通讲解...');​# 创建表 t_comment 并插入相关数据DROP TABLE IF EXISTS t_comment;CREATE TABLE t_comment(    id      int(20) NOT NULL AUTO_INCREMENT COMMENT '评论id',    content longtext COMMENT '评论内容',    author  varchar(200) DEFAULT NULL COMMENT '评论作者',    a_id    int(20)      DEFAULT NULL COMMENT '关联的文章id',    PRIMARY KEY (id)) ENGINE = InnoDB AUTO_INCREMENT = 3 DEFAULT CHARSET=utf8;INSERT INTO t_comment VALUES (1, '很全、很详细', 'lucy', 1);INSERT INTO t_comment VALUES (2, '赞一个', 'tom', 1);INSERT INTO t_comment VALUES (3, '很详细', 'eric', 1);INSERT INTO t_comment VALUES (4, '很好,非常详细', '张三', 1);INSERT INTO t_comment VALUES (5, '很不错', '李四', 2);
2)创建项目,引入相应的启动器

使用 Spring Initializr 来初始化项目。

项目名:springbootmybatis

包名:com.renda

启动器:SQL 的 MyBatis Framework、MySQL Driver,Web 的 Spring Web

3)编写与数据库表 t_comment 和 t_article 对应的实体类 Comment 和 Article

com.renda.pojo.Comment

public class Comment {    private Integer id;    private String content;    private String author;    private Integer aId;    // getter setter toString ...}

com.renda.pojo.Article

public class Article {    private Integer id;    private String title;    private String content;    // getter setter toString ...}
4)编写配置文件

application.properties 更名为 application.yml。在 application.properties 配置文件中进行数据库连接配置:

spring:  datasource:    url: jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC&characterEncoding=UTF-8    username: root    password: password
注解方式整合 Mybatis

需求:实现通过 ID 查询 Comment 信息。

1)创建一个对 t_comment 表数据操作的接口 CommentMapper

com.renda.mapper.CommentMapper

public interface CommentMapper {    @Select("select * from t_comment where id = #{id}")    Comment findById(Integer id);}
2)在 Spring Boot 项目启动类上添加 @MapperScan("xxx") 注解

com.renda.SpringbootmybatisApplication

@SpringBootApplication@MapperScan("com.renda.bootmybatis.mapper") //执行扫描mapper的包名public class SpringbootmybatisApplication {​    public static void main(String[] args) {        SpringApplication.run(SpringbootmybatisApplication.class, args);    }​}
3)编写测试方法

导入 Junit 的依赖,增加测试方法:

com.renda.SpringbootmybatisApplicationTests

@RunWith(SpringRunner.class)@SpringBootTestclass SpringbootmybatisApplicationTests {​    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")    @Autowired    private CommentMapper commentMapper;​    @Test    void findCommentById() {        Comment comment = commentMapper.findById(1);        System.out.println(comment);    }​}

控制台中查询的 Comment 的 aId 属性值为 null,没有映射成功。这是因为编写的实体类 Comment 中使用了驼峰命名方式将 t_comment 表中的 a_id 字段设计成了 aId 属性,所以无法正确映射查询结果。

为了解决上述由于驼峰命名方式造成的表字段值无法正确映射到类属性的情况,可以在 Spring Boot 全局配置文件 application.yml 中添加开启驼峰命名匹配映射配置,示例代码如下:

mybatis:  configuration:    # 开启驼峰命名匹配映射    map-underscore-to-camel-case: true
配置文件的方式整合 MyBatis

第一、二步骤使用 Free Mybatis plugin 插件生成:使用 IDEA 连接 Database,然后选中要自动生成代码的表,右键 -> mybatis-generator -> 按照需求输入信息,点击 ok。

1)创建一个用于对数据库表 t_article 数据操作的接口 ArticleMapper

public interface ArticleMapper {    int deleteByPrimaryKey(Integer id);​    int insert(Article record);​    int insertSelective(Article record);​    Article selectByPrimaryKey(Integer id);​    int updateByPrimaryKeySelective(Article record);​    int updateByPrimaryKey(Article record);}
2)创建 XML 映射文件

resources 目录下创建一个统一管理映射文件的包 mapper,并在该包下编写与 ArticleMapper 接口方应的映射文件 ArticleMapper.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ";><mapper namespace="com.renda.mapper.ArticleMapper">  <resultMap id="BaseResultMap" type="com.renda.pojo.Article">    <id column="id" jdbcType="INTEGER" property="id" />    <result column="title" jdbcType="VARCHAR" property="title" />    <result column="content" jdbcType="VARCHAR" property="content" />  </resultMap>  <sql id="Base_Column_List">    id, title, content  </sql>  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">    select     <include refid="Base_Column_List" />    from t_article    where id = #{id,jdbcType=INTEGER}  </select>  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">    delete from t_article    where id = #{id,jdbcType=INTEGER}  </delete>  <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.renda.pojo.Article" useGeneratedKeys="true">    insert into t_article (title, content)    values (#{title,jdbcType=VARCHAR}, #{content,jdbcType=VARCHAR})  </insert>  <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.renda.pojo.Article" useGeneratedKeys="true">    insert into t_article    <trim prefix="(" suffix=")" suffixOverrides=",">      <if test="title != null">        title,      </if>      <if test="content != null">        content,      </if>    </trim>    <trim prefix="values (" suffix=")" suffixOverrides=",">      <if test="title != null">        #{title,jdbcType=VARCHAR},      </if>      <if test="content != null">        #{content,jdbcType=VARCHAR},      </if>    </trim>  </insert>  <update id="updateByPrimaryKeySelective" parameterType="com.renda.pojo.Article">    update t_article    <set>      <if test="title != null">        title = #{title,jdbcType=VARCHAR},      </if>      <if test="content != null">        content = #{content,jdbcType=VARCHAR},      </if>    </set>    where id = #{id,jdbcType=INTEGER}  </update>  <update id="updateByPrimaryKey" parameterType="com.renda.pojo.Article">    update t_article    set title = #{title,jdbcType=VARCHAR},      content = #{content,jdbcType=VARCHAR}    where id = #{id,jdbcType=INTEGER}  </update></mapper>
3)配置 XML 映射文件路径

在项目中编写的 XML 映射文件,Spring Boot 并无从知晓,所以无法扫描到该自定义编写的 XML 配置文件,还必须在全局配置文件 application.yml 中添加 MyBatis 映射文件路径的配置,同时需要添加实体类别名映射路径,示例代码如下:

mybatis:  configuration:    # 开启驼峰命名匹配映射    map-underscore-to-camel-case: true  # 加载 resources/mapper 文件夹下的所有的 xml 文件  mapper-locations: classpath:mapper/*.xml  # 配置 XML 映射文件中指定的实体类别名路径  type-aliases-package: com.renda.pojo
4)编写单元测试进行接口方法测试
@RunWith(SpringRunner.class)@SpringBootTestclass SpringbootmybatisApplicationTests {        @Autowired    private ArticleMapper articleMapper;​    @Test    void findArticleById() {        Article article = articleMapper.selectByPrimaryKey(1);        System.out.println(article);    }    }

Spring Boot 整合 Redis1)添加Redis依赖包

在项目的 pom.xml 中添加如下:

<!-- redis 依赖包 --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency>
2)配置 Redis 数据库连接

在 application.yml 中配置redis数据库连接信息,如下:

spring:  redis:    # Redis 服务器地址    host: 192.168.186.128    # Redis 服务器连接端口    port: 6379    jedis:      pool:        # 连接池最大连接数(使用负值表示没有限制)        max-active: 18        # 连接池最大阻塞等待时间(使用负值表示没有限制)        max-wait: 3000        # 连接池中的最大空闲连接        max-idle: 20        # 连接池中的最小空闲连接        min-idle: 2    # 连接超时时间(毫秒)    timeout: 3000    # Redis 数据库索引(默认为 0)    database: 0
3)编写 Redis 操作工具类

将 RedisTemplate 实例包装成一个工具类,便于对 redis 进行数据操作。

package com.renda.util;​import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;​import java.util.concurrent.TimeUnit;​/** * @author Renda Zhang * @since 2020-10-30 1:00 */@Componentpublic class RedisUtils {​    @Autowired    private RedisTemplate redisTemplate;​    /**     * 读取缓存     */    public Object get(final String key) {        return redisTemplate.opsForValue().get(key);    }​    /**     * 写入缓存     */    public boolean set(String key, Object value) {        boolean result = false;        try {            redisTemplate.opsForValue().set(key, value, 1, TimeUnit.DAYS);            result = true;        } catch (Exception e) {            e.printStackTrace();        }        return result;    }​    /**     * 更新缓存     */    public boolean getAndSet(final String key, String value) {        boolean result = false;        try {            redisTemplate.opsForValue().getAndSet(key, value);            result = true;        } catch (Exception e) {            e.printStackTrace();        }        return result;    }​    /**     * 删除缓存     */    public boolean delete(final String key) {        boolean result = false;        try {            redisTemplate.delete(key);            result = true;        } catch (Exception e) {            e.printStackTrace();        }        return result;    }}
4)测试

写一个测试用例类来完成对 redis 的整合。

@RunWith(SpringRunner.class)@SpringBootTestclass SpringbootmybatisApplicationTests {​    // 写入,key:1,value:mysql 数据库中 id 为 1 的 article 记录    @Autowired    private RedisUtils redisUtils;​    @Test    void writeRedis() {        redisUtils.set("1", articleMapper.selectByPrimaryKey(1));        System.out.println("success");    }​    @Test    void readRedis() {        Article article = (Article) redisUtils.get("1");        System.out.println(article);    }​}

SpringBoot 视图技术

支持的视图技术

前端模板引擎技术的出现,使前端开发人员无需关注后端业务的具体实现,只关注自己页面的呈现效果即可,并且解决了前端代码错综复杂的问题、实现了前后端分离开发。Spring Boot 框架对很多常用的模板引擎技术(如:FreeMarker、Thymeleaf、Mustache 等)提供了整合支持。

Spring Boot 不太支持常用的 JSP 模板,并且没有提供对应的整合配置,这是因为使用嵌入式 Servlet 容器的 Spring Boot 应用程序对于 JSP 模板存在一些限制 :

在 Jetty 和 Tomcat 容器中,Spring Boot 应用被打包成 war 文件可以支持 JSP。但 Spring Boot 默认使用嵌入式 Servlet 容器以 JAR 包方式进行项目打包部署,这种 JAR 包方式不支持 JSP。如果使用 Undertow 嵌入式容器部署 Spring Boot 项目,也不支持 JSP 模板。(Undertow 是红帽公司开发的一款基于 NIO 的高性能 Web 嵌入式服务器)Spring Boot 默认提供了一个处理请求路径 “/error” 的统一错误处理器,返回具体的异常信息。使用 JSP 模板时,无法对默认的错误处理器进行覆盖,只能根据 Spring Boot 要求在指定位置定制错误页面。

Thymeleaf

Thymeleaf 是一种现代的基于服务器端的 Java 模板引擎技术,也是一个优秀的面向 Java 的 XML、XHTML、HTML5 页面模板,它具有丰富的标签语言、函数和表达式,在使用 Spring Boot 框架进行页面设计时,一般会选择 Thymeleaf 模板。

Thymeleaf 语法

在 HTML 页面上使用 Thymeleaf 标签,Thymeleaf 标签能够动态地替换掉静态内容,使页面动态展示。

为了更直观的认识 Thymeleaf,下面展示一个在 HTML 文件中嵌入了 Thymeleaf 的页面文件,示例代码如下:

<!DOCTYPE html><html lang="en" xmlns:th=";>    <head>        <meta charset="UTF-8">        <link rel="stylesheet" type="text/css" media="all"              href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" />        <title>Thymeleaf</title>    </head>    <body>        <p th:text="${hello}">Hello Thymeleaf</p>    </body></html>

上述代码中,“xmlns:th="; 用于引入 Thymeleaf 模板引擎标签,使用关键字 th 标注标签是 Thymeleaf 模板提供的标签,其中,th:href="@{/css/gtvg.css}" 用于引入外联样式文件,th:text="${hello}" 用于动态显示标签文本内容。

常用标签:

th:insert - 布局标签,替换内容到引入的文件th:replace - 页面片段包含(类似 JSP 中的 include 标签)th:each - 元素遍历(类似 JSP 中的 c:forEach 标签)th:if - 条件判断,如果为真th:unless - 条件判断,如果为假th:switch - 条件判断,进行选择性匹配th:case - 条件判断,进行选择性匹配th:value - 属性值修改,指定标签属性值th:href - 用于设定链接地址th:src - 用于设定链接地址th:text - 用于指定标签显示的文本内容

标准表达式:

变量表达式- ${...}选择变量表达式 - *{...}消息表达式 - #{...}链接 URL 表达式 - @{...}片段表达式 - ~{...}变量表达式 ${...}

变量表达式 ${...} 主要用于获取上下文中的变量值,示例代码如下:

<p th:text="${title}">这是标题</p>

示例使用了 Thymeleaf 模板的变量表达式 ${...} 用来动态获取 P 标签中的内容,如果当前程序没有启动或者当前上下文中不存在 title 变量,该片段会显示标签默认值“这是标题”;如果当前上下文中存在 title 变量并且程序已经启动,当前 P 标签中的默认文本内容将会被 title 变量的值所替换,从而达到模板引擎页面数据动态替换的效果。

同时,Thymeleaf 为变量所在域提供了一些内置对象,具体如下所示:

#ctx:上下文对象#vars:上下文变量#locale:上下文区域设置#request:(仅限 Web Context)HttpServletRequest 对象#response:(仅限 Web Context)HttpServletResponse 对象#session:(仅限 Web Context)HttpSession 对象#servletContext:(仅限 Web Context)ServletContext 对象

结合上述内置对象的说明,假设要在 Thymeleaf 模板引擎页面中动态获取当前国家信息,可以使用 #locale 内置对象,示例代码如下:

The locale country is: <span th:text="${#locale.country}">China</span>

上述代码中,使用 th:text="${#locale.country}" 动态获取当前用户所在国家信息,其中标签内默认内容为 China,程序启动后通过浏览器查看当前页面时,Thymeleaf 会通过浏览器语言设置来识别当前用户所在国家信息,从而实现动态替换。

选择变量表达式 *{...}

选择变量表达式和变量表达式用法类似,一般用于从被选定对象而不是上下文中获取属性值,如果没有选定对象,则和变量表达式一样,示例代码如下:

<div th:object="${book}">    <p>titile: <span th:text="*{title}">标题</span>.</p></div>

*{title} 选择变量表达式获取当前指定对象 book 的 title 属性值。

消息表达式 #{...}

消息表达式 #{...} 主要用于 Thymeleaf 模板页面国际化内容的动态替换和展示,使用消息表达式 #{...} 进行国际化设置时,还需要提供一些国际化配置文件。

链接表达式 @{...}

链接表达式 @{...} 一般用于页面跳转或者资源的引入,在 Web 开发中占据着非常重要的地位,并且使用也非常频繁,示例代码如下:

<a th:href="@{(orderId=${o.id})}">view</a> <a th:href="@{/order/details(orderId=${o.id},pid=${p.id})}">view</a>

上述代码中,链接表达式 @{...} 分别编写了绝对链接地址和相对链接地址。在有参表达式中,需要按照 @{路径(参数名称=参数值,参数名称=参数值...)} 的形式编写,同时该参数的值可以使用变量表达式来传递动态参数值。

片段表达式 ~{...}

片段表达式 ~{...} 用来标记一个片段模板,并根据需要移动或传递给其他模板。其中,最常见的用法是使用 th:insertth:replace 属性插入片段,示例代码如下:

<div th:insert="~{thymeleafDemo::title}"></div>

上述代码中,使用 th:insert 属性将 title 片段模板引用到该标签中。thymeleafDemo 为模板名称,Thymeleaf 会自动查找 /resources/templates/ 目录下的 thymeleafDemo 模板,title 为片段名称。

基本使用

1) Thymeleaf 模板基本配置

首先在 Springbootdemo2 项目中使用 Thymeleaf 模板,首先必须保证引入 Thymeleaf 依赖,示例代码如下:

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

其次,在全局配置文件中配置 Thymeleaf 模板的一些参数。一般 Web 项目都会使用下列配置,示例代码如:

spring:  thymeleaf:    # 在开发阶段,为了验证建议关闭缓存    cache: true    # 模板编码    encoding: UTF-8    # 应用于模板的模板模式    mode: HTML5    # 指定模板页面存放路径    prefix: classpath:/templates/    # 指定模板页面名称的后缀    suffix: .html

上述配置中,spring.thymeleaf.cache 表示是否开启 Thymeleaf 模板缓存,默认为 true,在开发过程中通常会关闭缓存,保证项目调试过程中数据能够及时响应;spring.thymeleaf.prefix 指定了 Thymeleaf 模板页面的存放路径,默认为classpath:/templates/spring.thymeleaf.suffix 指定了 Thymeleaf 模板页面的名称后缀,默认为 .html

2)静态资源的访问

开发 Web 应用时,难免需要使用静态资源。Spring boot 默认设置了静态资源的访问路径。

使用 Spring Initializr 方式创建的 Spring Boot 项目,默认生成了一个 resources 目录,在 resources 目录中的 public、resources、static 三个子目录下,Spring boot 默认会挨个从public、resources、static 里面查找静态资源。

完成数据的页面展示

1)创建 Spring Boot 项目,引入 Thymeleaf 依赖。

2)编写配置文件。

编辑 application.yml 全局配置文件,在该文件中对 Thymeleaf 模板页面的数据缓存进行设置。

# thymeleaf 页面缓存设置(默认为 true),开发中方便调试应设置为 false,上线稳定后应保持默认 truespring:  thymeleaf:    cache: false

使用 spring.thymeleaf.cache=false 将 Thymeleaf 默认开启的缓存设置为了 false,用来关闭模板页面缓存。

3)创建 web 控制类

在项目中创建名为 com.renda.controller 的包,并在该包下创建一个用于前端模板页面动态数据替换效果测试的访问实体类 LoginController

@Controllerpublic class LoginController {​    @RequestMapping("/toLogin")    public String toLoginView(Model model){        model.addAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR));        return "login"; // resources/templates/login.html    }​}

toLoginView() 方法用于向登录页面 login.html 跳转,同时携带了当前年份信息 currentYear

4)创建模板页面并引入静态资源文件。

classpath:/templates/ 目录下引入一个用户登录的模板页面 login.html

<!DOCTYPE html><html lang="en" xmlns:th=";><head>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1,shrink-to-fit=no">    <title>用户登录界面</title>    <link th:href="@{../static/css/bootstrap.min.css}" rel="stylesheet">    <link th:href="@{../static/css/signin.css}" rel="stylesheet"></head><body class="text-center"><!--  用户登录 form 表单 --><form class="form-signin">    <img class="mb-4" th:src="@{../static/img/login.png}" width="72" height="72">    <h1 class="h3 mb-3 font-weight-normal">请登录</h1>    <input type="text" class="form-control"           th:placeholder="用户名" required="" autofocus="">    <input type="password" class="form-control"           th:placeholder="密码" required="">    <div class="checkbox mb-3">        <label>            <input type="checkbox" value="remember-me"> 记住我        </label>    </div>    <button class="btn btn-lg btn-primary btn-block" type="submit" >登录</button>    <p class="mt-5 mb-3 text-muted">© <span th:text="${currentYear}">2019</span>-<span th:text="${currentYear}+1">2020</span></p></form></body></html>

通过 xmlns:th=" 引入了 Thymeleaf 模板标签;

使用 th:hrefth:src 分别引入了两个外联的样式文件和一个图片;

使用 th:text 引入了后台动态传递过来的当前年份 currentYear

5)效果测试

可以看出,登录页面 login.html 显示正常,在页面底部动态显示了当前日期 2020-2021,而不是文件中的静态数字 2019-2020。这进一步说明了 Spring Boot 与 Thymeleaf 整合成功,完成了静态资源的引入和动态数据的显示。

SpringBoot 实战演练

实战技能补充:lombok

<dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.18.12</version>    <!-- 编译期间生效 -->    <scope>provided</scope></dependency>

需求:实现用户的 CRUD 功能

初始化数据库信息:

DROP TABLE IF EXISTS `user`;CREATE TABLE `user`(    id int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',    username varchar(100) DEFAULT NULL COMMENT '用户名',    password varchar(100) DEFAULT NULL COMMENT '密码',    birthday varchar(100) DEFAULT NULL COMMENT '生日',    PRIMARY KEY (id)) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET=utf8;INSERT INTO `user` VALUES (1, 'zhangsan', '123', '2020-10-1');INSERT INTO `user` VALUES (2, 'lisi', '123', '2020-10-2');INSERT INTO `user` VALUES (3, 'wangwu', '123', '2020-10-10');INSERT INTO `user` VALUES (4, 'yuanjing', '123', '2020-10-11');
1)创建 springboot 工程

使用 Spring Initializr 新建一个工程 springbootuser,选择依赖:Developer Tools -> Lombok,Web -> Spring Web,SQL -> [MyBatis Framework、MySQL Driver]。

2)编辑 pom.xml

<!-- 引入阿里巴巴数据库连接池 --><dependency>    <groupId>com.alibaba</groupId>    <artifactId>druid</artifactId>    <version>1.1.3</version></dependency>
3)User 实体类编写

使用 FreeMyBatis 生成实体类。

使用 FreeMyBatis 生成 UserMapper 相关的代码。

com.renda.pojo.User

@Data // Lombok 自动生成 getter 和 setterpublic class User implements Serializable {    /**     * 用户id     */    private Integer id;​    /**     * 用户名     */    private String username;​    /**     * 密码     */    private String password;​    /**     * 生日     */    private String birthday;​    private static final long serialVersionUID = 1L;}
4)UserMapper 编写及 xml 文件

com.renda.mapper.UserMapper

public interface UserMapper {    int deleteByPrimaryKey(Integer id);​    int insert(User record);​    int insertSelective(User record);​    User selectByPrimaryKey(Integer id);​    int updateByPrimaryKeySelective(User record);​    int updateByPrimaryKey(User record);}

src\main\resources\mapper\UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ";><mapper namespace="com.renda.mapper.UserMapper">  <resultMap id="BaseResultMap" type="com.renda.pojo.User">    <id column="id" jdbcType="INTEGER" property="id" />    <result column="username" jdbcType="VARCHAR" property="username" />    <result column="password" jdbcType="VARCHAR" property="password" />    <result column="birthday" jdbcType="VARCHAR" property="birthday" />  </resultMap>  <sql id="Base_Column_List">    id, username, `password`, birthday  </sql>  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">    select     <include refid="Base_Column_List" />    from user    where id = #{id,jdbcType=INTEGER}  </select>  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">    delete from user    where id = #{id,jdbcType=INTEGER}  </delete>  <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.renda.pojo.User" useGeneratedKeys="true">    insert into user (username, `password`, birthday      )    values (#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{birthday,jdbcType=VARCHAR}      )  </insert>  <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.renda.pojo.User" useGeneratedKeys="true">    insert into user    <trim prefix="(" suffix=")" suffixOverrides=",">      <if test="username != null">        username,      </if>      <if test="password != null">        `password`,      </if>      <if test="birthday != null">        birthday,      </if>    </trim>    <trim prefix="values (" suffix=")" suffixOverrides=",">      <if test="username != null">        #{username,jdbcType=VARCHAR},      </if>      <if test="password != null">        #{password,jdbcType=VARCHAR},      </if>      <if test="birthday != null">        #{birthday,jdbcType=VARCHAR},      </if>    </trim>  </insert>  <update id="updateByPrimaryKeySelective" parameterType="com.renda.pojo.User">    update user    <set>      <if test="username != null">        username = #{username,jdbcType=VARCHAR},      </if>      <if test="password != null">        `password` = #{password,jdbcType=VARCHAR},      </if>      <if test="birthday != null">        birthday = #{birthday,jdbcType=VARCHAR},      </if>    </set>    where id = #{id,jdbcType=INTEGER}  </update>  <update id="updateByPrimaryKey" parameterType="com.renda.pojo.User">    update user    set username = #{username,jdbcType=VARCHAR},      `password` = #{password,jdbcType=VARCHAR},      birthday = #{birthday,jdbcType=VARCHAR}    where id = #{id,jdbcType=INTEGER}  </update></mapper>
5)UserService 接口及实现类编写

com.renda.service.UserService

public interface UserService {​    /**     * 查询所有     */    List<User> queryAll();​    /**     * 通过 ID 查询     */    User findById(Integer id);​    /**     * 新增     */    void insert(User user);​    /**     * 通过 ID 删除     */    void deleteById(Integer id);​    /**     * 修改     */    void update(User user);​}

com.renda.service.impl.UserServiceImpl

@Servicepublic class UserServiceImpl implements UserService {​    @Autowired    private UserMapper userMapper;​    @Override    public List<User> queryAll() {        return userMapper.queryAll();    }​    @Override    public User findById(Integer id) {        return userMapper.selectByPrimaryKey(id);    }​    @Override    public void insert(User user) {        // 将除 id 外所有的列都拼接入 SQL 语句        // userMapper.insert(user);        // 只将不为空的列才拼接入 SQL 语句(优先使用,减少高并发下数据传输)        userMapper.insertSelective(user);    }​    @Override    public void deleteById(Integer id) {        userMapper.deleteByPrimaryKey(id);    }​    @Override    public void update(User user) {        userMapper.updateByPrimaryKeySelective(user);    }​}
6)UserController 编写

com.renda.controller.UserController

/** * restful 格式进行访问 * 查询:GET * 新增: POST * 更新:PUT * 删除: DELETE * * @author Renda Zhang * @since 2020-10-31 1:36 */@RestController@RequestMapping("/user")public class UserController {​    @Autowired    private UserService userService;​    /**     * 查询所有     */    @GetMapping("/query")    public List<User> queryAll(){        return userService.queryAll();    }​    /**     * 通过 ID 查询     */    @GetMapping("/query/{id}")    public User queryById(@PathVariable Integer id){        return userService.findById(id);    }​    /**     * 删除     */    @DeleteMapping("/delete/{id}")    public String delete(@PathVariable Integer id){        userService.deleteById(id);        return "删除成功";    }​    /**     * 新增     */    @PostMapping("/insert")    public String insert(User user){        userService.insert(user);        return "新增成功";    }​    /**     * 修改     */    @PutMapping("/update")    public String update(User user){        userService.update(user);        return "修改成功";    }​}
7)全局配置文件 application.yml

重命名 application.propertiesapplication.yml

src\main\resources\application.yml

# 服务器配置server:  port: 8090​spring:  # 数据源配置  datasource:    name: druid    type: com.alibaba.druid.pool.DruidDataSource    url: jdbc:mysql://localhost:3306/springbootdata?characterEncoding=utf-8&serverTimezone=UTC    username: root    password: password​# 整合 MyBatismybatis:  # 声明 MyBatis 文件所在的位置  mapper-locations: classpath:mapper/*Mapper.xml
8)启动类

com.renda.SpringbootuserApplication

@SpringBootApplication// 使用的 Mybatis, 扫描 com.renda.mapper@MapperScan("com.renda.mapper")public class SpringbootuserApplication {​    public static void main(String[] args) {        SpringApplication.run(SpringbootuserApplication.class, args);    }​}
10)使用 Postman 测试GET GET POST PUT DELETE

Spring Boot 项目部署

需求:将 Spring Boot 项目使用 maven 指令打成 jar 包并运行测试。

分析

1)添加打包组件将项目中的资源、配置、依赖包打到一个 jar 包中;可以使用 maven 的 package 命令。

2)部署:java -jar 包名

步骤实现

确保 pom.xml 文件中有如下的打包组件:

<build>    <plugins>        <!-- 打 jar 包时如果不配置该插件,打出来的 jar 包没有清单文件 -->        <plugin>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-maven-plugin</artifactId>        </plugin>    </plugins></build>

部署运行:

java -jar springbootuser-0.0.1-SNAPSHOT.jar

想了解更多,欢迎关注我的微信公众号:Renda_Zhang

标签: #spring数据访问层