1.使用Mybatis实现数据库编程
在一个项目中,除了关联表,绝大部分的数据表都至少需要实现以下功能:
- 插入1条数据
- 批量插入数据
- 根据id删除某1条数据
- 根据若干个id批量删除某些数据
- 根据id修改数据
- 统计当前表中数据的数量
- 根据id查询数据详情
- 查询当前表中的数据列表
-
以“相册”(
pms_album
)为例,先实现“插入1条数据”的数据访问功能,需要执行的SQL语句大致是: -
INSERT INTO pms_album (除了id和2个时间以外的字段列表) VALUES (匹配的值列表);
要实现以上功能,需要:
- 在配置类中使用
@MapperScan
指定接口文件所在的根包- 一次性配置
- 在配置文件中通过
mybatis.mapper-locations
属性来指定XML文件所在的位置- 一次性配置
- 创建实体类
- 创建接口,并声明抽象方法
- 添加XML文件,并在此文件中配置抽象方法映射的SQL语句
- 创建测试类,编写并执行测试方法
- 非必要,但强烈推荐
则在项目的根包下创建config.MybatisConfiguration
配置类(添加了@Configuration
注解的类),在此类上配置@MapperScan
注解(工程名包下要被扫描的mapper文件夹reference地址):
package cn.tedu.csmall.product.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@MapperScan("cn.tedu.csmall.product.mapper")
@Configuration
public class MybatisConfiguration {
}
在application.properties
中添加配置:
# Mybatis相关配置
mybatis.mapper-locations=classpath:mapper/*.xml
并且,在src/main/resources
下创建名为mapper
的文件夹。
在编写POJO类之前,先在项目中添加依赖:
<!-- Lombok的依赖项,主要用于简化POJO类的编写 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
在任何POJO类上,可以添加@Data
注解,则此框架(Lombok)会自动在编译期生成:
- 各属性对应的Setters & Getters
- 基于各属性的
hashCode()
与equals()
- 基于各属性的
toString()
另外,所有POJO类都应该实现Serializable
接口!
在项目的根包下创建pojo.entity.Album
类,在类中声明与数据表对应的各属性:
package cn.tedu.csmall.product.pojo.entity;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 相册
*
* @author java@tedu.cn
* @version 0.0.1
*/
@Data
public class Album implements Serializable {
/**
* 记录id
*/
private Long id;
/**
* 相册名称
*/
private String name;
/**
* 相册简介
*/
private String description;
/**
* 自定义排序序号
*/
private Integer sort;
/**
* 数据创建时间
*/
private LocalDateTime gmtCreate;
/**
* 数据最后修改时间
*/
private LocalDateTime gmtModified;
}
在项目的根包下创建mapper.AlbumMapper
接口,并在接口中添加“插入1条数据”的抽象方法:
package cn.tedu.csmall.product.mapper;
import cn.tedu.csmall.product.pojo.entity.Album;
/**
* 处理相册数据的Mapper接口
*
* @author java@tedu.cn
* @version 0.0.1
*/
public interface AlbumMapper {
/**
* 插入相册数据
*
* @param album 相册数据
* @return 受影响的行数
*/
int insert(Album album);
}
关于抽象方法的声明:
- 返回值类型:如果执行的SQL语句是增、删、改类型的,返回值类型始终使用
int
,表示“受影响的行数”,也可以使用void
,但不推荐 - 方法名称:自定义,但不推荐重载
- 阿里巴巴的参考:
- 获取单个对象的方法用 get 做前缀
- 获取多个对象的方法用 list 做前缀
- 获取统计值的方法用 count 做前缀
- 插入的方法用 save/insert 做前缀
- 删除的方法用 remove/delete 做前缀
- 修改的方法用 update 做前缀
- 阿里巴巴的参考:
- 参数列表:根据需要执行的SQL语句中的参数来设计,如果参数较多,且具有相关性,则推荐封装
在src/main/resource/mapper
下,通过粘贴得到AlbumMapper.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="cn.tedu.csmall.product.mapper.AlbumMapper">
<!-- int insert(Album album); -->
<insert id="insert">
INSERT INTO pms_album (
name, description, sort
) VALUES (
#{name}, #{description}, #{sort}
)
</insert>
</mapper>
最后,在src/test/java
下的根包下,创建mapper.AlbumMapperTests
类,在类上添加@SpringBootTest
注解,并在类中编写测试方法:
package cn.tedu.csmall.product.mapper;
import cn.tedu.csmall.product.pojo.entity.Album;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class AlbumMapperTests {
@Autowired
AlbumMapper mapper;
@Test
void insert() {
Album album = new Album();
album.setName("测试相册002");
album.setDescription("测试相册简介002");
album.setSort(255);
int rows = mapper.insert(album);
System.out.println("插入相册数据完成,受影响的行数:" + rows);
}
}
附录:MySQL数据类型与Java类中的数据类型的对应关系
MySQL数据类型 | Java类中的数据类型 |
---|---|
tinyint / smallint / int | Integer |
bigint | Long |
char / varchar / text 系列 | String |
datetime | LocalDateTime |
晚课:密码加密
用户注册时(管理员添加新的账号信息时)的密码必须经过某种算法进行编码,并将得到的结果存储到数据库,而不允许将原始密码直接存储到数据库中!
原始密码通常可以称之为密码的原文,或称之为明文密码,经过编码处理的结果可称之为密文.
对明文密码进行编码处理时,不可以使用任何加密算法,因为所有加密算法都是可以逆向运算的,即:根据算法类型、加密参数、密文,可以通过运算得到密码原文!通常,加密算法只是用于保障数据在传输过程中的安全性!
对于需要存储下来的密码,且只需要验证原密码是否匹配,不需要(不允许)通过逆向运算根据密文得到原文时,应该使用消息摘要算法对密码原文进行编码处理!
消息摘要算法的典型特征有:
- 消息相同时,摘要必然相同
- 使用固定的某种消息摘要算法时,无论消息的长度多少,摘要的长度是固定的
- 消息不同时,摘要极大概率不会相同
- 理论上,必然存在N个不同的消息,通过编码,得到的摘要是完全相同的
- 由于摘要的种类也非常多,设计得非常好的算法会使得这种概率非常低
- 所有消息摘要算法都是不可以逆向运算的
消息摘要算法的结果通常会使用十六进制数来表示,通常,运算结果相同简单的消息摘要算法的结果长度也有32位十六进制数组成,还原成二进制数就是128个二进制数组成,这样的算法称之“128位算法”,同理,如果某个结果是由64个十六进制数组成,还原成二进制就是256个二进制数,则称之为“256位算法”。
以128位算法为例,其运算结果的种类将高达2的128次方种,即:340282366920938463463374607431768211456,以现有的计算机的算法,是不可能进行穷举式的暴力破解的!如果是256位算法,甚至更高位数的算法,更加不可能暴力破解!
常见的消息算法有:
- MD(Message Digest)系列
- MD2(128位,不推荐) / MD4(128位,不推荐) / MD5(128位)
- SHA(Secure Hash Algorithm)家族
- SHA-1(160位,不推荐) / SHA-256(256位) / SHA-384(384位) / SHA-512(512位)
在Spring Boot项目中,已有DigestUtils
工具类,提供了使用MD5算法进行编码的API