学习目标:
掌握实战项目各种开发过程
学习内容:
某某项目的源码实操,记录常用的“姿势”,
例如:
- 架构设计
- 掌握 Java 基本语法
- 分析各种常用的类以及方法
- 掌握开发必备技巧
- 分析源码
学习时间:
`7.14
项目涉及的注解类
接口实现类中常用到的注解
@Transactional(rollbackFor = Exception.class)
-
Java 中,事务是一组操作,要么全部成功,要么全部失败。在关系型数据库中,事务通常是指一组 SQL 操作,这些操作要么全部执行成功,要么全部回滚。
当发生异常或错误时,事务会自动回滚,以保证数据的一致性和完整性。
可以将 rollbackFor 属性设置为其他异常类型,例如 RuntimeException,表示在发生 RuntimeException 异常时回滚事务。 -
如果不指定 rollbackFor 属性,则默认只会在发生 RuntimeException 或 Error 异常时回滚事务。
(ps:public class RuntimeException extends Exception) -
@Transactional 注解只能应用于 public 访问权限的方法
Mapper接口常用注解
@Param
用于指定方法参数的名称,以便在 SQL 查询语句中引用它们。
Mapper接口
Mapper接口(xml)的标签
在Mapper.xml中,有很多的标签
<sql id="limit">
</sql>
#这里的id要对应Mapper.java接口中定义的方法,如:
Long limit();
<if test="pageParam != null">
#判断一个名为 "pageParam" 的参数是否为 null。
#如果 "pageParam" 参数不为 null,则条件语句返回 true,否则返回 false。
#<if> 标签提供了一种方便和灵活的方式来动态生成 SQL 语句,以便根据不同的条件生成不同的查询结果。
<select id="a" resultType="java.lang.Long">
#"resultType" 属性:指定查询结果的类型,这里是一个 Java 的 Long 类型。
<include refid="a"/>
#<include> 标签提供了一种方便和可重用的方式来引用 SQL 片段,以便动态生成 SQL 语句,避免了手动拼接 SQL 语句的繁琐。
举例子:
<sql id="a">
<where>
<if test="startTime != null">
and create_time >= #{startTime}
</if>
<if test="endTime != null">
and create_time <= #{endTime}
</if>
</where>
</sql>
<select id="getUserList" resultType="User">
select * from user
<include refid="a"/>
</select>
#这样,下边的sql语句就引用了上边id为a的sql片段
limit
SQL 中,LIMIT 是一个用于限制查询结果集的子句。它通常用于控制查询结果的数量或限制查询结果的范围。
经常配合分页查询来使用
SELECT * FROM user LIMIT 10, 10;
#可以查询 "user" 表中第 11 条到第 20 条记录:
COUNT(*)
COUNT(*) 函数来统计满足指定条件的记录数量
表的别名
select count(*) from user a
#这里把user表的别名取为a,可以简化代码
LEFT JOIN
表示左连接,它会返回左表中所有记录以及符合连接条件的右表记录,如果右表中没有匹配的记录,则返回 NULL 值。
users 表:
+----+-------+--------+
| id | name | gender |
+----+-------+--------+
| 1 | Alice | Female |
| 2 | Bob | Male |
| 3 | Carol | Female |
+----+-------+--------+
orders 表:
+----+---------+-------+
| id | user_id | price |
+----+---------+-------+
| 1 | 1 | 1000 |
| 2 | 2 | 2000 |
| 3 | 2 | 1500 |
+----+---------+-------+
SELECT users.id, users.name, SUM(orders.price) as total_price
FROM users
LEFT JOIN orders ON users.id = orders.user_id
GROUP BY users.id, users.name;
最终结果:
+----+-------+-------------+
| id | name | total_price |
+----+-------+-------------+
| 1 | Alice | 1000 |
| 2 | Bob | 3500 |
| 3 | Carol | NULL |
+----+-------+-------------+
左表 "users" 中的所有记录都被保留下来,并且如果右表 "orders" 中存在符合条件的记录,则计算订单总金额。如果右表中没有符合条件的记录,则返回 NULL 值。
order by
ORDER BY 子句用于对查询结果进行排序。它可以按照一个或多个列的值进行升序或降序排序
ORDER BY 子句中,可以使用 DESC 关键字来指定降序排序
SELECT name, score
FROM student
ORDER BY score DESC;
“#” 符号表示引用变量,可以动态替换变量的值。
#{searchParams.userCode}
${…}
${…} 是一种常用的占位符语法,它可以将 Java 代码中的变量值动态地注入到 SQL 查询语句中。
注意:在 MyBatis 中,**#{} 和 ${} 都是用于占位符的语法,**用于将 Java 对象中的属性值动态地注入到 SQL 查询语句中。
- #{} 是一个预编译的占位符,可以防止 SQL 注入攻击,同时也可以自动处理特殊字符转义等问题,参数可以是任意类型,MyBatis 会自动根据参数的类型进行转换。例如,如果 #{age} 的值是一个整数类型,则 MyBatis 会将它转换为 SQL 中的整数类型。
- ${} 是一个简单的字符串替换,可以将变量值直接替换到 SQL 语句中。它不会对参数进行预处理和转义,也不会防止 SQL 注入攻击。因此,使用 ${} 时需要特别小心,需要确保参数的值是安全的,并且需要手动处理特殊字符转义等问题。参数只能是字符串类型,如果参数是其他类型,需要手动进行转换。
and
SQL 查询语句中,AND 是一个逻辑运算符,用于将多个条件连接起来,并且同时满足这些条件。如果所有条件都成立,则返回结果
SELECT *
FROM employee
WHERE gender = '男' AND salary >= 5000 AND salary <= 8000;
like
LIKE 是一个关键字,用于模糊匹配字符型数据。它通常用于查询某个字段中包含特定字符串的记录。
SELECT *
FROM employee
WHERE name LIKE '%张%';
# % 通配符来表示任意长度的任意字符,可以匹配包含 "张" 字符的任意字符串。
# _:表示一个任意字符,可以出现在模式的任意位置。
CONCAT
字符串函数,用于将多个字符串连接起来
concat('%', #{Params.userCode}, '%')
# 可以和like关键字结合使用
# like concat('%', #{Params.userCode}, '%')
项目涉及的对象
DigestUtils.md5DigestAsHex()
用于计算给定输入的 MD5 哈希值,并将结果以十六进制字符串的形式返回。
String input = "hello world";
byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8);
String hash = DigestUtils.md5DigestAsHex(inputBytes);
System.out.println(hash);
getBytes
String input = "hello world";
byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8);
可以结合上边的DigestUtils.md5DigestAsHex():
DigestUtils.md5DigestAsHex(input.getBytes(StandardCharsets.UTF_8))
//通常用来给密码加盐,达到把明文密码变成密文密码的作用
StandardCharsets
Java 7 中引入的一个类,它包含了一些常用的字符集常量。这些常量可以用于指定 String 类型和 byte[] 类型之间的字符集编码和解码
一般我们都用来进行这两个类型的字符集编码和解码
UTF_8: 表示 UTF-8 字符集。
UTF_16BE: 表示 UTF-16 大端序字节顺序的字符集。
UTF_16LE: 表示 UTF-16 小端序字节顺序的字符集。
UTF_16: 表示 UTF-16 字符集,使用默认字节顺序(即根据平台的大端或小端顺序自动选择字节顺序)。
US_ASCII: 表示 US-ASCII 字符集。
ISO_8859_1: 表示 ISO-8859-1 字符集,也称为 Latin-1 字符集。
最常用的就是UTF_8
Dao层的对象
项目涉及的技巧
数据库分页
1.设置参数
public static final Long DEFAULT_PAGE_NUM = 1L;
//默认请求页数,从1开始
public static final Long DEFAULT_PAGE_SIZE = 10L;
//请求页大小,默认为 10
2.设置构造函数(无参,有参)
初始化用户(自动化)
在xxxImpl中,一般我们会通过查询用户是否存在,然后判断,存在则直接登录,不存在就进行注册
1.要创建一个初始化的类,比如xx.init(userId)(根据用户id来创建)
private Long UserAccount(Long userId) {
// 根据编号直接查询用户是否存在,存在则直接登录,不存在则进行注册
UserDO userDO = userDao.getByUserId(userId);
if (userDO == null) {
userDO = UserConverter.init(userId);
}
userDao.saveOrUpdateBindInfo(userDO);
return userId;
}
2.在初始化类中进行相关设置:
public class UserConverter {
public static UserDO init(Long userId) {
UserDO userAiDO = new UserDO();
userDO.setUserId(userId);
userDO.setrNumber("");
userDO.setType(0);
userDO.setInviterUserId(0L);
userDO.setStrategy(0);
userDO.setInviteNum(0);
userDO.setDeleted(0);
userAiDO.setInviteCode(UserRandomGenHelper.genInviteCode(userId));
userAiDO.setState(UserAIStatEnum.IGNORE.getCode());
return userAiDO;
}
}
项目必备方法
longValue()
该方法可以将 Integer 类型的值转换为对应的 long 类型值,如果 转换的值超出了 Long 类型的取值范围,转换后的值可能会失真或溢出。
因此,在进行类型转换时需要注意数据范围的问题,避免出现数据错误或异常
继承封装分页查询的相关信息
例子:
PageParam 类用于封装分页查询的相关信息,包括当前页码、每页记录数、OFFSET 和 LIMIT 参数等。
Search 类则用于封装查询条件,例如审核状态、编号、登录用户名和用户编号等。
通过继承 PageParam 类,Search 类可以在进行分页查询时,使用 PageParam 类中定义的页码和每页记录数等分页参数。同时,Search 类还可以添加自己的属性和方法,用于封装查询条件。
可以避免重复代码。如果没有继承 PageParam 类,那么在每个查询方法中都需要设置页码和每页记录数等分页参数,这样会导致代码冗余和重复。
new Random();
new Random() 是 Java 中用于创建一个随机数生成器对象的语法
可以用于生成不同类型的随机数,例如整数、浮点数和布尔值等
nextInt()
生成一个随机的整数,该方法接受一个整数参数,表示生成的随机数的范围
Random().nextInt(100)//可以生成一个小于 100 的随机整数
nextDouble()
生成一个随机的双精度浮点数,该方法生成的随机数的范围是 0.0 到 1.0 之间
Random().nextDouble() //生成一个介于 0.0 和 1.0 之间的随机双精度浮点数。