SpringBoot+MyBatis+MySQL电脑商城项目实战(二)用户注册—持久层

用户注册

1 创建数据表

  1. 选中数据表
use store
  1. 创建t_user
CREATE TABLE t_user (
	uid INT AUTO_INCREMENT COMMENT '用户id',
	username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',
	`password` CHAR(32) NOT NULL COMMENT '密码',
	salt CHAR(36) COMMENT '盐值',
	phone VARCHAR(20) COMMENT '电话号码',
	email VARCHAR(30) COMMENT '电子邮箱',
	gender INT COMMENT '性别:0-女,1-男',
	avatar VARCHAR(50) COMMENT '头像',
	is_delete INT COMMENT '是否删除:0-未删除,1-已删除',
	created_user VARCHAR(20) COMMENT '日志-创建人',
	created_time DATETIME COMMENT '日志-创建时间',
	modified_user VARCHAR(20) COMMENT '日志-最后修改执行人',
	modified_time DATETIME COMMENT '日志-最后修改时间',
	PRIMARY KEY (uid)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

2 创建用户实体类

  1. 通过表的结构提取出表的公共字段,放在一个实体类的基类中,起名叫BaseEntity基类中
  • 声明私有属性变量
  • 声明私有属性的get,set方法
  • 生成equals和hashCode()方法
  • toString()方法
package com.cy.store.entity;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;
import java.util.Objects;

/**
 * 作为实体类的基类
 */
//@Data
public class BaseEntity implements Serializable {
    private String createdUser;
    private Date createdTime;
    private String modifiedUser;
    private Date modifiedTime;

    public String getCreatedUser() {
        return createdUser;
    }

    public void setCreatedUser(String createdUser) {
        this.createdUser = createdUser;
    }

    public Date getCreatedTime() {
        return createdTime;
    }

    public void setCreatedTime(Date createdTime) {
        this.createdTime = createdTime;
    }

    public String getModifiedUser() {
        return modifiedUser;
    }

    public void setModifiedUser(String modifiedUser) {
        this.modifiedUser = modifiedUser;
    }

    public Date getModifiedTime() {
        return modifiedTime;
    }

    public void setModifiedTime(Date modifiedTime) {
        this.modifiedTime = modifiedTime;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        BaseEntity that = (BaseEntity) o;

        if (!Objects.equals(createdUser, that.createdUser)) return false;
        if (!Objects.equals(createdTime, that.createdTime)) return false;
        if (!Objects.equals(modifiedUser, that.modifiedUser)) return false;
        return Objects.equals(modifiedTime, that.modifiedTime);
    }

    @Override
    public String toString() {
        return "BaseEntity{" +
                "createdUser='" + createdUser + '\'' +
                ", createdTime=" + createdTime +
                ", modifiedUser='" + modifiedUser + '\'' +
                ", modifiedTime=" + modifiedTime +
                '}';
    }

    @Override
    public int hashCode() {
        int result = createdUser != null ? createdUser.hashCode() : 0;
        result = 31 * result + (createdTime != null ? createdTime.hashCode() : 0);
        result = 31 * result + (modifiedUser != null ? modifiedUser.hashCode() : 0);
        result = 31 * result + (modifiedTime != null ? modifiedTime.hashCode() : 0);
        return result;
    }
}
  1. 创建用户的实体类。需要继承BaseEntity基类
package com.cy.store.entity;

import java.io.Serializable;
import java.util.Objects;

/**
 * 用户的实体类:SpringBoot约定大于配置
 */
public class User extends BaseEntity implements Serializable {
    private Integer uid;
    private String username;
    private String password;
    private String salt;
    private String phone;
    private String email;
    private Integer gender;
    private String avatar;
    private Integer isDelete;

    //1、get和set方法,equals和hashCode(),toString()方法


    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public Integer getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(Integer isDelete) {
        this.isDelete = isDelete;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;

        User user = (User) o;

        if (!Objects.equals(uid, user.uid)) return false;
        if (!Objects.equals(username, user.username)) return false;
        if (!Objects.equals(password, user.password)) return false;
        if (!Objects.equals(salt, user.salt)) return false;
        if (!Objects.equals(phone, user.phone)) return false;
        if (!Objects.equals(email, user.email)) return false;
        if (!Objects.equals(gender, user.gender)) return false;
        if (!Objects.equals(avatar, user.avatar)) return false;
        return Objects.equals(isDelete, user.isDelete);
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + (uid != null ? uid.hashCode() : 0);
        result = 31 * result + (username != null ? username.hashCode() : 0);
        result = 31 * result + (password != null ? password.hashCode() : 0);
        result = 31 * result + (salt != null ? salt.hashCode() : 0);
        result = 31 * result + (phone != null ? phone.hashCode() : 0);
        result = 31 * result + (email != null ? email.hashCode() : 0);
        result = 31 * result + (gender != null ? gender.hashCode() : 0);
        result = 31 * result + (avatar != null ? avatar.hashCode() : 0);
        result = 31 * result + (isDelete != null ? isDelete.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", salt='" + salt + '\'' +
                ", phone='" + phone + '\'' +
                ", email='" + email + '\'' +
                ", gender=" + gender +
                ", avatar='" + avatar + '\'' +
                ", isDelete=" + isDelete +
                '}';
    }
}

3 注册-持久层

通过MyBatis来操作数据库。在做MyBatis开发的流程。

3.1 规划需要执行的SQL语句

  1. 用户的注册功能,相当于在做数据的插入操作。
insert into t_user(user,password) values (值列表)
  1. 在用户的注册时首先要去查询当前的用户名是否存在,如果存在则不能进行注册,相当于是一条查询语句。
select * from t_user where username = ?

3.2 设计接口和抽象方法

  1. 定义mapper接口。在项目的目录结构下首先创建一个mapper接口,在这个包下再根据不同的功能模块来创建mapper接口。创建一个UserMapper的接口。要在接口中定义这两个SQL语句的抽象方法。
  2. 在启动类配置mapper接口文件的位置
//MapperScan注解指定当前项目中的Mapper接口路径的位置,在项目启动的时候会自动加载所有的接口文件
@MapperScan("com.cy.mapper")

3.3 编写映射

  1. 定义xml映射文件,与对应的接口进行关联。所有的映射文件需要放置resources目录下,在这个目录下创建一个mapper文件夹,在这个文件夹下存放Mapper的映射文件。
  2. 创建接口对应的映射文件,遵循和接口的名称保持一致即可。创建一个UserMapper.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">
<!--namespace属性:用于指定当前的映射文件和哪个接口进行映射,需要指定接口的文件路径,需要标注包的完整路径结构-->
<mapper namespace="com.cy.store.mapper.UserMapper">
</mapper>
  1. 配置接口中的方法对应SQL语句上。需要借助标签来完成,insert/update/delete/select,对应的是SQL语句的增删改查操作。
<?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">
<!--namespace属性:用于指定当前的映射文件和哪个接口进行映射,需要指定接口的文件路径,需要标注包的完整路径结构-->
<mapper namespace="com.cy.store.mapper.UserMapper">
    <!--自定义映射规则:resultMap标签来完成映射规则的定义-->
    <!--
        id属性:标签给这个映射负责分配一个唯一的id值,对应的就是resultMap="id属性值"属性的取值
        type属性:取值是一个类,表示的时数据库中的查询结果与Java中哪个实体类进行结果集的映射
    -->
    <resultMap id="UserEntityMap" type="com.cy.store.entity.User">
        <!--将表的字段和类的属性不一致的字段进行匹配指定,名称一致的字段可以省略不写-->
        <!--
            配合完成名称不一致的映射
            column属性:表示表中的资源名称
            property属性:表示类中的属性名称
        -->
        <!--在定义映射规则时,主键是不可以省略的,无论名称是否一致-->
        <id column="id" property="uid"></id>
        <result column="is_delete" property="isDelete"></result>
        <result column="created_user" property="createdUser"></result>
        <result column="created_time" property="createdTime"></result>
        <result column="modified_user" property="modifiedUser"></result>
        <result column="modified_time" property="modifiedTime"></result>
    </resultMap>

    <!--id属性:表示映射的接口中方法的名称,直接在标签的内容部来编写SQL语句。-->
    <!--
        useGeneratedKeys属性:表示开启某个字段的值递增(主键设置为递增)
        keyProperty属性:表示将表中的哪个字段作为主键进行递增,uid不是uuid
    -->
    <insert id="insert" useGeneratedKeys="true" keyProperty="uid">
        insert into t_user(
            username, password,salt,phone,email,gender,avatar,
            is_delete,created_user,created_time,modified_user,
            modified_time
        ) values(
            #{username}, #{password},#{salt},#{phone},#{email},#{gender},
            #{avatar},#{isDelete},#{createdUser},#{createdTime}
            ,#{modifiedUser},#{modifiedTime})
    </insert>
    <!--select语句在执行的时候,查询的结果是一个对象,多个对象-->
    <!--ResultType:表示查询的结果集类型,只需要指定对应映射类的类型,并且包含完完整包接口-->
    <!--resultMap:表示当表的字段和类的对象属性的字段名称不一致时,来自定义查询结果集的映射规则。-->
    <select id="findByUsername" resultMap="UserEntityMap">
        select * from t_user where  username = #{username}
    </select>

</mapper>
  1. 单元测试:每个独立的层编写完毕后需要编写单元测试方法,来测试当前的功能。在test包结构下创建一个mapper包,在这个包下再创建持久层的功能测试。

    接口自动装配时,显示无法自动装配,显示红色波浪线的解决办法:
    setting→inspections→Spring→Spring Core
    image

package com.cy.store.mapper;
import com.cy.store.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
//@SpringBootTest:表示标注当前的类是一个测试类,不会随同项目一块打包
@SpringBootTest
//@RunWith:表示启动这个单元测试类(不写这个注解的话单元测试类是不能够运行的),需要传递一个参数,必须是SpringRunner的实例类型
@RunWith(SpringRunner.class)
public class UserMapperTests {
    /*
    * 报无法自动装载的原因:
    * idea有检测的功能,接口是不能够直接创建Bean的,MyBatis创建了接口的动态代理,实现类来完成了对象的创建(底层动态代理技术来解决)
    * */
    @Autowired
    private  UserMapper userMapper;
    /*单元测试方法特点:就可以单独独立运行,不用启动整个项目,可以做单元测试,提升了代码的测试效率
    * 1、必须被Test注解修饰
    * 2、返回值类型必须是void
    * 3、方法的参数列表不指定任何类型
    * 4、方法的访问修饰符必须是public
    * */
    @Test
    public void insert(){
        User user = new User();
        user.setUsername("water");
        user.setPassword("123");
        Integer rows = userMapper.insert(user);
        System.out.println(rows);
   }
   @Test
   public void findByUsername(){
       User user = userMapper.findByUsername("water");
       System.out.println(user);
   }
}
posted @ 2023-04-21 05:47  翻山越玲  阅读(106)  评论(0)    收藏  举报