目录

一、测试数据库连接

二、使用数据库连接池

三、导入数据表

四、使用代码生成器来生成项目中必要的代码

五、测试使用Mybatis Plus

六、关于业务


一、测试数据库连接

straw-api-usertest下,默认就已经存在StrawApiUserApplicationTests测试类,并且测试类中已经存在contextLoads()测试方法,先直接执行该方法的单元测试:

用chatgpt写springcloud代码_数据库

由于以上测试中没有任何代码,所以,执行单元测试是应该能通过测试的,如果没有通过测试,一定是开发环境出了问题,例如jar包文件是损坏的,正常的执行效果例如:

用chatgpt写springcloud代码_代码生成器_02

当以上测试通过后,自定义方法,执行“连接数据库”的测试:

用chatgpt写springcloud代码_xml_03

如果在application.properties中配置的登录数据库的用户名或密码错误,测试会失败,并且会出现提示:  

用chatgpt写springcloud代码_xml_04

以上错误的提示信息是:

java.sql.SQLException: Access denied for user 'root1234'@'localhost' (using password: YES)

 其中,using password: YES就表示已经配置了密码,'root1234'@'localhost'表示使用root1234作为用户名,登录到了localhost这台数据库服务器,所以,可以通过以上信息来检查用户名和密码的配置是否正确。

如果数据库的服务没有开启,或者配置的主机信息有误(例如主机名或端口号错误),会出现如下错误:

用chatgpt写springcloud代码_数据库_05

 错误信息是:

com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

如果测试成功,结果是:

用chatgpt写springcloud代码_数据库_06

 


二、使用数据库连接池

数据库连接池的种类较多,本项目中使用alibabadruid,依赖的参考代码是:

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

先在straw项目中管理以上依赖,并在straw-api-user中添加应用依赖。

然后,在straw-api-userapplication.properties中添加配置:

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.initial-size=2
spring.datasource.druid.max-active=10
spring.datasource.druid.min-idle=2

三、导入数据表

https://robinliu.3322.org:8888/download/demo/straw_v20200904.zip 下载数据库的脚本文件压缩包,解压得到数据库脚本文件,是以.sql为扩展名的文件。

得到.sql文件后,为了便于导入,将该文件放到E盘的根目录下(放到其它盘也可以),名为1.sql

登录MySQL控制台,使用straw数据库后,通过以下指令导入数据库脚本:

source e:\1.sql

注意:以上指令不要使用分号表示结束!

当导入成功后,可以看到,已经创建了多张数据表(其中,某些数据表中还有数据):

用chatgpt写springcloud代码_spring_07


四、使用代码生成器来生成项目中必要的代码

Mybatis Plus(偶尔简称为MP)是Mybatis的增强版,它不是Mybatis官方的框架,该框架已经定义好了常规的增删改查,例如插入数据、根据id删除数据、根据id修改数据、根据id查询数据、查询表中所有数据等功能,所以,在使用Mybatis Plus框架后,这些简单的数据操作都不需要自行编写代码,直接使用即可!

关于Mybatis Plus,依赖的参考代码是:

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.2</version>
</dependency>

然后,和此前的操作步骤相同,先在strawpom.xml中管理以上依赖,然后在straw-api-user中应用以上依赖。

虽然Mybatis Plus已经极大程度的简化了持久层开发,但是,作者并满足于此,他认为每个项目中,针对每张数据表都需要创建Mapper接口文件,还需要创建配置SQL语句的XML文件,每张数据表还需要对应的实体类等等,这些操作是不具备技术含量的,所以,作者还开发了Mybatis Plus Generator(代码生成器)项目,它的作用就是“根据数据表结构”直接创建出所需要的所有基础文件,并存放在对应的包中,文件包括:

  • 实体类;
  • 持久层Mapper接口文件;
  • 持久层配置SQL语句的XML文件;
  • 业务层的接口文件;
  • 业务层的实现类文件;
  • 控制器层的控制器类文件。

关于代码生成器,应该在一个专门的项目中来使用,所以,先在straw下创建新的straw-generator子模块项目,这个项目的作用并不参与实际的功能开发,就只是用于生成以上文件的。

在创建子模块项目时,依然使用SpringBoot的创建向导来创建项目:

用chatgpt写springcloud代码_spring_08

在创建过程中,暂不勾选任何依赖。

然后,需要添加依赖,所需要的新的依赖的参考代码:

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-generator -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-extension -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-extension</artifactId>
    <version>3.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-freemarker -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
    <version>2.3.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>

strawpom.xml文件需要调整为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.tedu</groupId>
    <artifactId>straw</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>straw</name>
    <description>Demo project for Spring Boot</description>

    <packaging>pom</packaging>

    <properties>
        <java.version>1.8</java.version>
        <spring-boot.version>2.3.3.RELEASE</spring-boot.version>
        <mybatis.version>2.1.3</mybatis.version>
        <mysql.version>8.0.21</mysql.version>
        <druid.version>1.1.23</druid.version>
        <mybatis-plus.version>3.3.2</mybatis-plus.version>
        <lombok.version>1.18.12</lombok.version>
    </properties>

    <!-- 管理依赖 -->
    <dependencyManagement>
        <dependencies>
            <!-- Mybatis Plus Generator:代码生成器 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-generator</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>
            <!-- Mybatis Plus扩展:用于代码生成器 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-extension</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>
            <!-- SpringBoot FreeMarker:用于代码生成器 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
            <!-- Lombok:通过注解简化开发 -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <scope>provided</scope>
            </dependency>
            <!-- Mybatis Plus:简化Mybatis开发 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>
            <!-- druid:alibaba的数据库连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <!-- Mybatis -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
            <!-- MySQL -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
                <version>${mysql.version}</version>
            </dependency>
            <!-- web:允许项目启动在Tomcat -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
            <!-- 单元测试 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <version>${spring-boot.version}</version>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

然后,调整straw-generatorpom.xml文件,先设置父级项目:

用chatgpt写springcloud代码_spring_09

该项目需要添加的依赖有:

  • mysql:需要连接到数据库,分析数据表结构,才可以生成相关的文件;
  • mybatis-plus系列;
  • spring-boot-starter-freemarker
  • lombok:可以不添加,生成的代码会自动添加lombok的注解,如果不添加,则生成代码后straw-generator项目会报错,但是,这些生成的文件也会被移动到实际使用的项目中,所以不添加也不会影响。

关于straw-generatorpom.xml的代码:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>straw</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.tedu</groupId>
    <artifactId>straw-generator</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>straw-generator</name>

    <dependencies>
        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- Mybatis Plus:简化Mybatis开发 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!-- Mybatis Plus Generator:代码生成器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
        </dependency>
        <!-- Mybatis Plus扩展:用于代码生成器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
        </dependency>
        <!-- SpringBoot FreeMarker:用于代码生成器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!-- Lombok:通过注解简化开发 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

由于straw-generator并不用于开发实际的功能,所以启动类、单元测试等文件或文件夹都可以直接删除:

用chatgpt写springcloud代码_数据库_10

然后,将代码生成器的2个文件添加到项目中:

用chatgpt写springcloud代码_xml_11

CodeGenerator.java文件中,检查顶部的全局属性的值,可能需要修改为自定义的配置值(例如连接数据库的用户名、密码等)。

然后,点击Build菜单中的Rebuild选项,如果提示警告是正常的(因为在CodeGenerator.java中使用了已过期的方法)。

最后,运行CodeGenerator.javamain()方法,会出现提示,输入user表示将生成user数据表相关的文件:

用chatgpt写springcloud代码_代码生成器_12

生成成功时,控制台的输出例如:

用chatgpt写springcloud代码_spring_13

并且,在项目的结构中,可以看到生成的文件:

用chatgpt写springcloud代码_数据库_14

注意:生成的文件中,在mapper包下的xml包下的文件是多余的,应该将这个xml文件夹删掉:

用chatgpt写springcloud代码_spring_15

然后,将剩余的生成的文件复制到straw-api-user项目的对应位置:

用chatgpt写springcloud代码_代码生成器_16

最后,把straw-generator项目中生成的文件全部删除,仅保留用于生成文件的2个文件,以备下次使用:

用chatgpt写springcloud代码_spring_17

另外,还需要在straw-api-user项目中添加Mybaits Plus相关的依赖:

用chatgpt写springcloud代码_xml_18


 五、测试使用Mybatis Plus

straw-api-user中测试Mybatis Plus的使用,先在StrawApiUserApplication类的声明之前添加@MapperScan注解,以指定接口文件的包:

用chatgpt写springcloud代码_mybatis_19

并在application.properties中配置XML文件的位置:

用chatgpt写springcloud代码_spring_20

testcn.tedu.straw.api.user包下创建mapper.UserMapperTests测试类:

用chatgpt写springcloud代码_spring_21

然后,在测试类中添加测试方法,以测试Mybatis Plus的insert()方法:

用chatgpt写springcloud代码_mybatis_22

另外,还可以测试更多Mybatis Plus定义的功能:

package cn.tedu.straw.api.user.mapper;

import cn.tedu.straw.api.user.model.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class UserMapperTests {

    @Autowired
    UserMapper mapper;

    @Test
    void insert() {
        User user = new User();
        user.setUsername("旺财");
        user.setPassword("1234");
        user.setPhone("13800138002");
        int rows = mapper.insert(user);
        System.out.println("rows=" + rows);
    }

    @Test
    void deleteById() {
        Integer id = 1;
        int rows = mapper.deleteById(id);
        System.out.println("rows=" + rows);
    }

    @Test
    void updateById() {
        User user = new User();
        user.setId(4);
        user.setPassword("123456");
        user.setGender(1);
        user.setClassId(998);
        int rows = mapper.updateById(user);
        System.out.println("rows=" + rows);
    }

    @Test
    void selectById() {
        Integer id = 4;
        User user = mapper.selectById(id);
        System.out.println("user=" + user);
    }

}

Mybatis Plus虽然提供了大量的增删改查方法,使得开发人员不必自行定义增删改查,但是,有些操作使用时也并不方便,例如:

@Test
void selectByUsername() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("username", "大强"); // username='小强'
    User user = mapper.selectOne(queryWrapper);
    System.out.println("user=" + user);
}

如果查询的条件更加复杂,还要配置排序规则,或者还要配置Limit子句,使用就会更加麻烦,如果还涉及关联表查询,其实,还不如自行配置SQL语句来定义查询的功能!

即使使用了Mybatis Plus,也不影响自行定义数据访问的功能,例如,在UserMapper.java中添加:

@Repository
public interface UserMapper extends BaseMapper<User> {

    /**
     * 根据用户名查询用户数据
     * @param username 用户名
     * @return 匹配的用户数据,如果没有匹配的数据则返回null
     */
    User findByUsername(String username);

}

然后,在UserMapper.xml中配置以上抽象方法映射的SQL语句:

<select id="findByUsername" resultMap="BaseResultMap">
    SELECT * FROM user WHERE username=#{username}
</select>

最后,每次定义了新的方法,或修改了任何内容,都应该执行单元测试:

@Test
void findByUsername() {
    String username = "小黄";
    User user = mapper.findByUsername(username);
    System.out.println("user=" + user);
}

六、关于业务

业务(Service)是调用持久层,且被外部(例如控制器等其它组件)调用的组件,在大多数据情况下,数据的访问流程是:

用chatgpt写springcloud代码_mybatis_23

业务层主要负责的任务是:确定业务流程(先干什么,后干什么)、业务逻辑(什么情况下能干什么),以保证数据的完整性和安全性!

数据的安全性:数据是否根据所设定的规则而产生或发生变化。

为了实现解耦(通过接口来编程),业务层通常由业务接口(例如IUserService)和业务实现类(例如UserServiceImpl)组成,所以,在其它组件中调用业务层时,都会通过接口来声明业务对象!

可以在IUserService中添加“学生注册”的业务方法:

void registStudent(User user);

然后,在UserServiceImpl类中实现该方法:

@Autowired
UserMapper userMapper;

public void registStudent(User user) {
    // 规则:手机号/用户名必须是唯一的
    // 通过参数user.getUsername()获取注册的用户名
    // 调用User result = userMapper.findByUsername(String username)查询用户信息
    // 判断查询结果result是否为null
    // 是:根据用户名没有找到用户数据,则用户名没有被注册,则允许注册
    // // 调用int rows = userMapper.insert(user)插入用户数据
    // 否:根据用户名找到了用户数据,则用户名已经被注册,则不允许注册
    // // 暂时通过System.out.println()提示错误信息
}

testcn.tedu.straw.api.user下创建service.UserServiceTests测试类,测试业务方法:

@SpringBootTest
public class UserServiceTests {
    
    @Autowired
    IUserService service;
    
    @Test
    void registStudent() {
        // 调用注册方法,观察运行结果
    }
    
}