前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从零开始做网站2-springboot整合mybatis

从零开始做网站2-springboot整合mybatis

作者头像
sunonzj
发布2022-06-21 08:50:47
2170
发布2022-06-21 08:50:47
举报
文章被收录于专栏:zjblogzjblog

昨天把项目建好了,底子有了然后就是进行下一步开发了,先整合下Mybatis,使用Mybatis框架做数据持久化操作。

MyBatis配置模式是指使用mybatis配置文件的方式与SpringBoot进行整合,相对应的就有mybatis-config.xml(用于配置驼峰命名,也可以省略这个文件)、XxxMapper.xml文件。

主要步骤为:

导入mybatis官方starter

编写mapper接口。标准@Mapper注解

编写sql映射文件并绑定mapper接口

在application.yaml中指定Mapper配置文件的位置,以及指定全局配置文件的信息

注解模式使用

主要步骤:

导入mybatis官方依赖

注解方式编写mapper接口

在application.yaml中指定Mapper配置文件的位置,以及指定全局配置文件的信息

注解模式比配置模式少了编写Mapper.xml文件,简化了简单SQL语句的xml文件编写。

混合模式

在实际项目开发中涉及很多复杂业务及连表查询SQL,可以配合使用注解与配置模式,达到最佳实践的目的。

实际项目操作步骤:

引入mybatis-starter

配置application.yaml中,指定mapper-location位置即可

编写Mapper接口并标注@Mapper注解

简单方法直接注解方式

复杂方法编写mapper.xml进行绑定映射

主启动类上使用@MapperScan("com.fengye.springboot_mybatis.mapper") 简化Mapper接口,包下所有接口就可以不用标注@Mapper注解

1.导入mybatis整合依赖,mybatis-spring-boot-starter类似一个中间件,链接springBoot和Mybatis

代码语言:javascript
复制
        <!--   mybatis整合     -->
        <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

2.在SpringBoot配置文件中定义数据源,并整合mybatis相关的配置,去applicaton.properties配置一下数据库

代码语言:javascript
复制
#定义数据源
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456

#springboot整合mybatis的配置
#指定实体类位置,在mapper中就不用写全路径
mybatis.type-aliases-package: com.zjlovelt.entity
#映射mapper的位置,和dao层接口对应,一定要对应mapper映射xml文件的所在路径
mybatis.mapper-locations=classpath:mapping/*.xml
# 配置打印 SQL 语句
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

然后在SpringBoot启动类上添加mapper接口扫描注解

代码语言:javascript
复制
@SpringBootApplication
//添加扫描mybatis的dao层接口,生成实现类
@MapperScan(value = "com.zjlovelt.mapper")
public class LtBlogApplication {

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

}

在pom.xml 中添加资源打包配置

代码语言:javascript
复制
<build>
        <plugins>
        <resources>

            <!--没有写到 resources 目录下的 xml 文件需要以下配置-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <!--指定 resources 目录下的哪些文件需要编译-->
            <resource>
                <directory>src/main/resources</directory>
                <!-- excludes和includes二选一使用即可 -->
                <!-- 不包含的文件,支持通配符 -->
                <excludes>
                    <exclude>*.txt</exclude>
                </excludes>
                <!-- 包含的文件,支持通配符 -->
                <includes>
                    <include>*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>

            </resource>
        </resources>
    </build>

配置都搞完了,就可以开始测试了,测试一下查询文章详情的接口,看看数据库操作是否ok了

新建文章详情表

1.png
1.png

在数据库表中插入一条测试数据

image.png
image.png

新建实体类

代码语言:javascript
复制
package com.zjlovelt.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.zjlovelt.common.constance.Constance;
import com.zjlovelt.common.constance.DictionaryConstance;
import com.zjlovelt.mapper.SysDataDictionaryMapper;
import lombok.Data;

import java.io.Serializable;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.logging.SimpleFormatter;

@Data
public class ArticleInfo implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long articleId;
    private String type;        //类别
    private String title;       //文章标题
    private String articleImg;  //插图
    private String keyword;     //关键字/标签
    private String summary;     //摘要
    private String content;     //文章内容
    private String author;      //作者
    private String accessNum;   //浏览数
    private String status;      //状态(用于主页显示)

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Timestamp articleDate; //发布日期

    ......
    ......

    //临时字段
    private Boolean statusName; //用于接受前端参数
    private String articleDateStr; //用于接受前端参数
    private String typeName;
    private String statusStr;
    private String[] keywordArr;


    /**
     * code转名称
     *
     * @param sysDataDictionaryMapper
     */
    public void convertCodeToName(SysDataDictionaryMapper sysDataDictionaryMapper) {
        //文章类别
        if (this.getType() != null) {
            SysDataDictionary dataDictionary = sysDataDictionaryMapper.findByCategoryidAndValue(DictionaryConstance.ARTICLE_TYPE, this.getType());
            if (dataDictionary != null) {
                this.setTypeName(dataDictionary.getName());
            }
        }

        //文章状态
        if(this.getStatus() != null){
            if(this.getStatus().equals(Constance.DelFlag_NO)){
                this.setStatusStr("不推荐");
            }else{
                this.setStatusStr("推荐");
            }
        }

        //返回给前端的一些字段
        if(this.getStatus() != null){
            if(this.getStatus().equals(Constance.DelFlag_NO)){
                this.setStatusName(false);
            }else{
                this.setStatusName(true);
            }
        }
    }
}

新建dao层mapper接口

代码语言:javascript
复制
package com.zjlovelt.mapper;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zjlovelt.entity.ArticleInfo;
import com.zjlovelt.entity.SysDataDictionary;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ArticleInfoMapper {

    ArticleInfo selectByPrimaryKey(Long articleId);

}

新建mapper.xml

代码语言:javascript
复制
<?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.zjlovelt.mapper.ArticleInfoMapper" >
  <resultMap id="BaseResultMap" type="com.zjlovelt.entity.ArticleInfo" >
    <id column="article_id" property="articleId" jdbcType="BIGINT" />
    <result column="type" property="type" jdbcType="VARCHAR" />
    <result column="title" property="title" jdbcType="VARCHAR" />
    <result column="article_img" property="articleImg" jdbcType="VARCHAR" />
    <result column="keyword" property="keyword" jdbcType="VARCHAR" />
    <result column="summary" property="summary" jdbcType="VARCHAR" />
    <result column="author" property="author" jdbcType="VARCHAR" />
    <result column="access_num" property="accessNum" jdbcType="INTEGER" />
    <result column="status" property="status" jdbcType="CHAR" />
    <result column="article_date" property="articleDate" jdbcType="TIMESTAMP" />
    <result column="thumbs_num" property="thumbsNum" jdbcType="INTEGER" />
    <result column="parent" property="parent" jdbcType="VARCHAR" />
    <result column="pageUrl" property="pageUrl" jdbcType="VARCHAR" />
    <result column="update_by" property="updateBy" jdbcType="VARCHAR" />
    <result column="update_date" property="updateDate" jdbcType="TIMESTAMP" />
    <result column="create_by" property="createBy" jdbcType="VARCHAR" />
    <result column="create_date" property="createDate" jdbcType="TIMESTAMP" />
    <result column="remark" property="remark" jdbcType="VARCHAR" />
    <result column="del_flag" property="delFlag" jdbcType="CHAR" />
  </resultMap>
  <resultMap id="ResultMapWithBLOBs" type="com.zjlovelt.entity.ArticleInfo" extends="BaseResultMap" >
    <result column="content" property="content" jdbcType="LONGVARCHAR" />
  </resultMap>
  <sql id="Base_Column_List" >
    article_id, type, title, article_img, keyword, summary, author, access_num, status,
    article_date, thumbs_num, parent, pageUrl, update_by, update_date, create_by, create_date,
    remark, del_flag
  </sql>
  <sql id="Blob_Column_List" >
    content
  </sql>

  <select id="selectByPrimaryKey" resultMap="ResultMapWithBLOBs" parameterType="java.lang.Long" >
    select
    <include refid="Base_Column_List" />
    ,
    <include refid="Blob_Column_List" />
    from article_info
    where article_id = #{articleId,jdbcType=BIGINT}
  </select>
 
</mapper>

新建业务实现service层

代码语言:javascript
复制
package com.zjlovelt.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zjlovelt.common.constance.Constance;
import com.zjlovelt.common.id.IdGenerator;
import com.zjlovelt.common.result.Result;
import com.zjlovelt.mapper.ArticleInfoMapper;
import com.zjlovelt.entity.ArticleInfo;
import com.zjlovelt.mapper.SysDataDictionaryMapper;
import com.zjlovelt.shiro.JwtUtils;
import com.zjlovelt.utils.Tools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ArticleInfoService {

    @Autowired
    private ArticleInfoMapper articleInfoMapper;
    @Autowired
    private SysDataDictionaryMapper dataDictionaryMapper;


    public ArticleInfo getArticleInfo(Long articleId){
        ArticleInfo model = articleInfoMapper.selectByPrimaryKey(articleId);
        model.convertCodeToName(dataDictionaryMapper);
        return model;
    }

}

新建controller层

代码语言:javascript
复制
package com.zjlovelt.controller;

import com.zjlovelt.common.result.Result;
import com.zjlovelt.entity.ArticleInfo;
import com.zjlovelt.service.ArticleInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RequestMapping("/article")
@RestController
public class ArticleInfoController {

    @Autowired
    private ArticleInfoService articleInfoService;

    /**
     * 获取文章详情内容
     * @param id
     * @return
     */
    @RequestMapping("getInfoById")
    public ArticleInfo getInfoById(Long articleId){
        return articleInfoService.getArticleInfo(articleId);
    }

}

然后就是运行项目项目

再用postman测试接口

image.png
image.png

完美~

springboot整合mybatis中需要注意的地方

1.配置文件方面

        常见的有两种形式properties和yml格式,如果是yml格式务必注意空格的使用,不要用tab,有时不小心多敲一个空格也会让你格外的头疼。同时注意缩进的对齐。

2.出现Invalid bound statement (not found)错误

一般来说报这种错误,都会通过下面几种方法查找。

检查Mapper.xml的命名空间是否正确。这个主要检查的是namespace中的名字和其dao层的接口类是否对应。

检查dao层的方法名和Mapper.xml中的方法名是否一致。

检查Mapper.xml中的parameterType和resultMap/resultType是否正确。

查看mybatis的xml路径配置是否正确

3、项目结构问题

springboot项目在启动时会依据启动类所在包逐级向下扫描,如果你的dao层,service层和controller层在一个模块中,一定要把他们放到启动类所在目录或者他的子目录下。如果是多模块配置通过依赖的形式使用那么一定要注意包名的书写,和启动类所在包名保持一样,因为它是以包名进行的扫描。所以乱写的话会直接导致扫描不到需要的组件bean

————————————————————

之前建的Springboot项目打包方式是war,后面改成jar重新选择了。

改变理由:之所以选war是因为对war最熟悉,之前工作基本都是这个,对tomcat也很了解,而且war包后面部署好修改代码可以局部更新某一个文件,但是jar就不行了,不过还是选择用jar是因为做这个项目毕竟是为了学习,自然不能一直用熟悉的,而且jar有个好处就是到时候部署肯定和我自己博客在一个服务器,部署个jar包也不用放在一个tomcat下面或者再去配个tomcat了,考虑深远,完美~

选war包和jar包创建的spring boot目录有点小区别,首先是这个ServletInitializer类没有 具体区别可以参考:

https://www.jianshu.com/p/cb5cb5937686

最后,开发计划更新~~ 后面会一直更新开发计划,因为文章是在开发时写的,而发布是在后面,所以文章发布时间会比实际开发和写文章的日期要晚点。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档