文章目录
- 1 帖子表 discuss_post
- 1.1 字段描述
- 1.2 相关功能描述
- 1.2.1 分页查询帖子
- 1.2.2 查询帖子总数量
- 1.2.3 插入一条帖子记录
- 1.2.4 根据帖子ID查询某条帖子
- 1.2.5 更新帖子评论数量
- 1.2.6 更新帖子类型
- 1.2.6 更新帖子状态
- 1.2.7 更新帖子分数
- 2 用户表 user
- 2.1 字段描述
- 2.2 相关功能描述
- 2.2.1 根据用户ID查询用户
- 2.2.2 通过用户名查询用户
- 2.2.3 根据用户邮箱查询用户
- 2.2.4 插入一条用户记录
- 2.2.5 更新用户状态
- 2.2.6 更新用户头像
- 2.2.7 更新用户密码
- 3 登录凭证表 login_ticket
- 3.1 字段描述
- 3.2 相关功能描述
- 3.2.1 插入一条登录凭证记录
- 3.2.2 根据凭证字符串查询登录凭证
- 3.2.3 根据凭证字符串修改对应登录凭证的状态
- 4 评论表 comment
- 4.1 字段描述
- 4.2 相关功能描述
- 4.2.1 分页查询某个帖子的回帖,查询某个回帖下的所有评论和回复
- 4.2.2 查询某条帖子的回帖数量,查询回帖下的评论和回复数量
- 4.2.3 插入一条comment记录(回帖/评论/回复)
- 4.2.4 根据comment 的 id查询回帖/评论/回复
- 5 消息表 message
- 5.1 字段描述
- 5.2 相关功能描述
- 5.2.1 分页查询某个用户的所有私信,按会话id分组,每组只有一条最新的私信
- 5.2.2 根据userId,查询某个用户所有会话的数量
- 5.2.3 根据conversation_id查询消息列表
- 5.2.4 查询某个用户未读消息数量,查询某个用户的某个会话id下的未读消息数量
- 5.2.5 新增一条消息记录
- 5.2.6 根据消息ids,修改一批消息的状态
- 5.2.7 查询某个用户的,某个通知事件类型的,一条最新通知
- 5.2.8 查询某个用户的,某个通知事件类型的,通知数量
- 5.2.9 查询某个用户的未读通知数量,查询某个用户的某个通知事件类型的未读通知数量
- 5.2.10 分页查询某个用户的,某个通知事件类型的通知
1 帖子表 discuss_post
1.1 字段描述
描述 | 字段 | 类型 |
---|---|---|
帖子Id,主键 | id | int |
贴子所属的用户id,帖子是由谁发表的 | user_id | varchar(45) |
帖子标题 | title | varchar(100) |
帖子内容 | content | text |
帖子类型:0-普通; 1-置顶; | type | int |
帖子状态:0-正常; 1-精华; 2-删除; | status | int |
帖子创建时间 | create_time | timestamp |
帖子评论数量(回帖、评论、回复) | comment_count | int |
帖子分数(根据分数进行热度排行) | score | double |
1.2 相关功能描述
1.2.1 分页查询帖子
对应接口
List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit, int orderMode);
注意事项
- 以下所有查询都是查未被删除的帖子,即status != 2。
- 如果userId不为0,即要查询某个用户的帖子。
- 如果 orderMode 为 0,先按照帖子类型(置顶1、普通0)降序排序,让置顶的帖子放在前面,type一样的帖子按照时间顺序降序排序,让先发表的帖子放在前面。
- 如果 orderMode 为 1,表示按照热度查询,先按照帖子类型(置顶1、普通0)降序排序,让置顶的帖子放在前面,type一样的帖子分数降序排序,让分数高的帖子放在前面,如果分数一样,按照时间排序,把先发布的帖子放在前面。
对应SQL
<select id="selectDiscussPosts" resultType="DiscussPost">
select <include refid="selectFields"></include>
from discuss_post
where status != 2
<if test="userId!=0">
and user_id = #{userId}
</if>
<if test="orderMode==0">
order by type desc, create_time desc
</if>
<if test="orderMode==1">
order by type desc, score desc, create_time desc
</if>
limit #{offset}, #{limit}
</select>
1.2.2 查询帖子总数量
对应接口
int selectDiscussPostRows(@Param("userId") int userId);
注意事项
- 查询的是查未被删除的帖子,即status != 2。
- 如果userId不为0,表明要查询某个用户发布的帖子总数量,此时应该假设where条件判断。
对应SQL
<select id="selectDiscussPostRows" resultType="int">
select count(*)
from discuss_post
where status != 2
<if test="userId!=0">
and user_id = #{userId}
</if>
</select>
1.2.3 插入一条帖子记录
对应接口
int insertDiscussPost(DiscussPost discussPost);
注意事项
传入的是帖子对象
对应SQL
<insert id="insertDiscussPost" parameterType="DiscussPost" keyProperty="id">
insert into discuss_post(<include refid="insertFields"></include>)
values(#{userId},#{title},#{content},#{type},
#{status},#{createTime},#{commentCount},#{score})
</insert>
1.2.4 根据帖子ID查询某条帖子
对应接口
DiscussPost selectDiscussPostById(int id);
注意事项
查询的是未被删除的帖子,所以status != 2。
对应SQL
<select id="selectDiscussPostById" resultType="DiscussPost">
select <include refid="selectFields"></include>
from discuss_post
where status != 2 and id = #{id}
</select>
1.2.5 更新帖子评论数量
对应接口
int updateCommentCount(int id, int commentCount);
注意事项
更新帖子评论数量要和新增帖子放在同一个事务中,防止出现数据不一致问题。
对应SQL
<update id="updateCommentCount">
update discuss_post set comment_count = #{commentCount} where id = #{id}
</update>
1.2.6 更新帖子类型
对应接口
int updateType(int id, int type);
注意事项
对应SQL
<update id="updateType">
update discuss_post set type = #{type} where id = #{id}
</update>
1.2.6 更新帖子状态
对应接口
int updateStatus(int id, int status);
注意事项
对应SQL
<update id="updateStatus">
update discuss_post set status = #{status} where id = #{id}
</update>
1.2.7 更新帖子分数
对应接口
int updateScore(int id, double score);
注意事项
对应SQL
<update id="updateScore">
update discuss_post set score = #{score} where id = #{id}
</update>
2 用户表 user
2.1 字段描述
描述 | 字段 | 类型 |
---|---|---|
用户id | id | int |
用户名 | username | varchar(50) |
用户密码 | password | varchar(50) |
盐 | salt | varchar(50) |
用户邮箱 | varchar(100) | |
用户类型:0-普通用户; 1-超级管理员; 2-版主; | type | int |
用户状态:0-未激活; 1-已激活; | status | int |
注册用户的激活码 | activation_code | varchar(100) |
用户头像 | header_url | varchar(200) |
用户创建时间 | create_time | timestamp |
2.2 相关功能描述
2.2.1 根据用户ID查询用户
对应接口
User selectById(int id);
注意事项
对应SQL
<select id="selectById" resultType="User">
select <include refid="selectFields"></include>
from user
where id = #{id}
</select>
2.2.2 通过用户名查询用户
对应接口
User selectByName(String username);
注意事项
对应SQL
<select id="selectByName" resultType="User">
select <include refid="selectFields"></include>
from user
where username = #{username}
</select>
2.2.3 根据用户邮箱查询用户
对应接口
User selectByEmail(String email);
注意事项
对应SQL
<select id="selectByEmail" resultType="User">
select <include refid="selectFields"></include>
from user
where email = #{email}
</select>
2.2.4 插入一条用户记录
对应接口
int insertUser(User user);
注意事项
对应SQL
<insert id="insertUser" parameterType="User" keyProperty="id">
insert into user (<include refid="insertFields"></include>)
values(#{username}, #{password}, #{salt}, #{email}, #{type}, #{status}, #{activationCode}, #{headerUrl}, #{createTime})
</insert>
2.2.5 更新用户状态
对应接口
int updateStatus(int id, int status);
注意事项
对应SQL
<update id="updateStatus">
update user set status = #{status} where id = #{id}
</update>
2.2.6 更新用户头像
对应接口
int updateHeader(int id, String headerUrl);
注意事项
对应SQL
<update id="updateHeader">
update user set header_url = #{headerUrl} where id = #{id}
</update>
2.2.7 更新用户密码
对应接口
int updatePassword(int id, String password);
注意事项
对应SQL
<update id="updatePassword">
update user set password = #{password} where id = #{id}
</update>
3 登录凭证表 login_ticket
3.1 字段描述
描述 | 字段 | 类型 |
---|---|---|
登录凭证id | id | int |
用户id,谁的登录凭证 | user_id | int |
登录凭证字符串,一串UUID,保证每个登录用户不重复 | ticket | varchar(45) |
0-有效; 1-无效; | status | int |
过期时间,一段时间后登录凭证会过期,用户需要重新登录 | expired | timestamp |
3.2 相关功能描述
3.2.1 插入一条登录凭证记录
对应接口
int insertLoginTicket(LoginTicket loginTicket);
注意事项
在插入一条登录凭证信息后需要将主键id回填,useGeneratedKeys = true, keyProperty = “id”
我觉得这个回填功能并没有使用到
对应SQL
@Insert({
"insert into login_ticket(user_id,ticket,status,expired) ",
"values(#{userId},#{ticket},#{status},#{expired})"
})
// @Options(useGeneratedKeys = true, keyProperty = "id") // 这个回填并没有被使用到。
3.2.2 根据凭证字符串查询登录凭证
对应接口
LoginTicket selectByTicket(String ticket);
注意事项
对应SQL
@Select({
"select id,user_id,ticket,status,expired ",
"from login_ticket where ticket=#{ticket}"
})
3.2.3 根据凭证字符串修改对应登录凭证的状态
对应接口
int updateStatus(String ticket, int status);
注意事项
对应SQL
@Update({
"<script>",
"update login_ticket set status=#{status} where ticket=#{ticket} ",
"<if test=\"ticket!=null\"> ",
"and 1=1 ",
"</if>",
"</script>"
})
以下是对代码的解释:
解释 MyBatis 注解中的 @Update
使用
这段代码是一个 MyBatis 框架中使用的数据库更新操作的注解定义。这里使用的是 MyBatis 的动态 SQL 特性来构造 SQL 更新语句。让我们逐一分析这个代码的组成部分:
-
@Update
注解:@Update
是用于标识一个方法执行数据库的更新操作(即 SQL 的UPDATE
语句)。- 在大括号
{}
内部,你可以定义实际执行的 SQL 语句。
-
使用
<script>
标签:<script>
标签在这里用来包围可能包含动态 SQL 部分的 SQL 语句。- MyBatis 使用 XML 类似的标签来处理动态 SQL 语句,即使在注解中也可以使用这些标签。
-
更新语句:
update login_ticket set status=#{status} where ticket=#{ticket}
是一个基础的 SQL 更新语句,它的作用是更新login_ticket
表中的status
字段。更新的条件是ticket
字段等于方法参数ticket
的值。
-
使用
<if>
标签进行条件判断:<if test=\"ticket!=null\">
是一个条件语句,用来检查输入参数ticket
是否不为null
。- 这里的条件实际上并没有改变 SQL 逻辑,因为
and 1=1
是一个总是为真的条件。这种写法通常用于测试或者作为编写更复杂逻辑的占位符。
-
方法签名:
int updateStatus(String ticket, int status);
这个方法接收两个参数:ticket
和status
,并返回一个整型值,表示更新操作影响的行数。- 在 MyBatis 中,更新操作通常返回一个整数,表示 SQL 语句影响的行数。
总结来说,这段代码通过 MyBatis 注解定义了一个更新数据库中 login_ticket
表的操作。它使用动态 SQL 来确保只有当 ticket
不为 null
时才执行更新,虽然在这个特定的示例中,and 1=1
没有实际的过滤作用,更多的可能是为了展示如何在条件内部使用固定的真值条件。
4 评论表 comment
4.1 字段描述
描述 | 字段 | 类型 |
---|---|---|
回帖/评论/回复id | id | int |
用户id,这条回帖/评论/回复是谁发的 | user_id | int |
在哪个实体类型下面:1-帖子;2-回帖 | entity_type | int |
实体id | entity_id | int |
被回复的用户id,0-不是回复,是回帖或评论,不为0-回复的用户id | target_id | int |
回帖/评论/回复的内容 | content | text |
回帖/评论/回复的状态:0-正常;1-删除 | status | int |
回帖/评论/回复的创建时间 | create_time | timestamp |
可以这样理解:在帖子下的评论,和在评论下的评论
也可以按照下面的理解
以这三条数据为例
以下是另外一组数据:
)
4.2 相关功能描述
4.2.1 分页查询某个帖子的回帖,查询某个回帖下的所有评论和回复
对应接口
List<Comment> selectCommentsByEntity(int entityType, int entityId, int offset, int limit);
注意事项
- 查询的回帖/评论/回复都是存在的,未被删除的,即 status = 0
- 当 entityType = 1:表示需要分页查询某个帖子下所有的回帖,此时会利用offset和limit参数
- 当 entityType = 2:表示需要查询某个回帖下的所有评论和回复,此时ofsset = 0, limit = Integer.MAX_VALUE
对应SQL
<select id="selectCommentsByEntity" resultType="Comment">
select <include refid="selectFields"></include>
from comment
where status = 0
and entity_type = #{entityType}
and entity_id = #{entityId}
order by create_time asc
limit #{offset}, #{limit}
</select>
4.2.2 查询某条帖子的回帖数量,查询回帖下的评论和回复数量
对应接口
int selectCountByEntity(int entityType, int entityId);
注意事项
- 当 entiyType = 1:查询某条帖子的回帖数量,用于分页显示计算回帖页数。
- 当 entiyType = 2:查询回帖下的评论和回复数量,用于前端页面显示某条回帖下的评论和回复数量。
对应SQL
<select id="selectCountByEntity" resultType="int">
select count(id)
from comment
where status = 0
and entity_type = #{entityType}
and entity_id = #{entityId}
</select>
4.2.3 插入一条comment记录(回帖/评论/回复)
对应接口
int insertComment(Comment comment);
注意事项
对应SQL
<insert id="insertComment" parameterType="Comment">
insert into comment(<include refid="insertFields"></include>)
values(#{userId},#{entityType},#{entityId},#{targetId},#{content},#{status},#{createTime})
</insert>
4.2.4 根据comment 的 id查询回帖/评论/回复
对应接口
Comment selectCommentById(int id);
注意事项
对应SQL
<select id="selectCommentById" resultType="Comment">
select <include refid="selectFields"></include>
from comment
where id = #{id}
</select>
5 消息表 message
5.1 字段描述
消息id | id | int |
---|---|---|
消息发送方id:1-系统;大于1-用户id | from_id | int |
消息接收方用户id | to_id | int |
对话id或通知事件类型:小用户id_大用户id,表示是对话id;like/follow/comment,表示是通知事件类型 | conversation_id | varchar(45) |
消息的内容 | content | text |
消息状态:0-未读;1-已读;2-删除; | status | int |
消息创建时间 | create_time | timestamp |
可以这样理解:在帖子下的评论,和在评论下的评论
5.2 相关功能描述
5.2.1 分页查询某个用户的所有私信,按会话id分组,每组只有一条最新的私信
对应接口
List<Message> selectConversations(int userId, int offset, int limit);
注意事项
- 这个查询比较复杂,要嵌套查询,先查出每个会话最大的消息id,再查询这些消息id对应的完整的信息,按时间降序排序,只显示offset开始的limit条记录。
- 要选择未被删除的消息,所以status != 2
- 要选择的是私信,所以from_id != 1
- 要查的是user_id的对话信息,所以是from_id = #{userId} or to_id = #{userId}
对应SQL
<select id="selectConversations" resultType="Message">
select <include refid="selectFields"></include>
from message
where id in (
select max(id) from message
where status != 2
and from_id != 1
and (from_id = #{userId} or to_id = #{userId})
group by conversation_id
)
order by id desc
limit #{offset}, #{limit}
</select>
5.2.2 根据userId,查询某个用户所有会话的数量
对应接口
int selectConversationCount(int userId);
注意事项
- 用于分页显示用户会话
- 要选择未被删除的消息,所以status != 2
- 要查询的是会话的数量,所以from_id != 1
- 要查的是user_id的对话信息,所以是from_id = #{userId} or to_id = #{userId}
对应SQL
我觉得直接使用这个SQL要比课程里面的要好。
select count(*) from message
where status != 2
and from_id != 1
and (from_id = 111 or to_id = 111)
group by conversation_id
5.2.3 根据conversation_id查询消息列表
对应接口
int selectLetterCount(String conversationId);
注意事项
对应SQL
我觉得这里不用写from_id != 1
<select id="selectLetterCount" resultType="int">
select count(id)
from message
where status != 2
// and from_id != 1
and conversation_id = #{conversationId}
</select>
5.2.4 查询某个用户未读消息数量,查询某个用户的某个会话id下的未读消息数量
对应接口
int selectLetterUnreadCount(int userId, String conversationId);
注意事项
- 是查询未读消息,消息发送发一定是已读的,所以要用to_id筛选
- 未读消息,status = 0
对应SQL
<select id="selectLetterUnreadCount" resultType="int">
select count(id)
from message
where status = 0
and from_id != 1
and to_id = #{userId}
<if test="conversationId!=null">
and conversation_id = #{conversationId}
</if>
</select>
5.2.5 新增一条消息记录
对应接口
int insertMessage(Message message);
注意事项
- 如果是私信,由程序执行,同步添加
- 如果是通知,由消息队列,然后异步添加
对应SQL
<insert id="insertMessage" parameterType="Message" keyProperty="id">
insert into message(<include refid="insertFields"></include>)
values(#{fromId},#{toId},#{conversationId},#{content},#{status},#{createTime})
</insert>
5.2.6 根据消息ids,修改一批消息的状态
对应接口
int updateStatus(List<Integer> ids, int status);
注意事项
对应SQL
<update id="updateStatus">
update message set status = #{status}
where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</update>
5.2.7 查询某个用户的,某个通知事件类型的,一条最新通知
对应接口
Message selectLatestNotice(int userId, String topic);
注意事项
- 要查询的是通知,所以from_id = 1
- 不能是已经删除的通知,所以status != 2
- 查询某个用户的通知,所以to_id = #{userId}
对应SQL
也可以按时间降序排序,然后limit 1,只返回1条,就是最新的那条通知
<select id="selectLatestNotice" resultType="Message">
select <include refid="selectFields"></include>
from message
where id in (
select max(id) from message
where status != 2
and from_id = 1
and to_id = #{userId}
and conversation_id = #{topic}
)
</select>
5.2.8 查询某个用户的,某个通知事件类型的,通知数量
对应接口
int selectNoticeCount(int userId, String topic);
注意事项
- 要查询的是通知,所以from_id = 1
- 不能是已经删除的通知,所以status != 2
- 查询某个用户的通知,所以to_id = #{userId}
对应SQL
<select id="selectNoticeCount" resultType="int">
select count(id) from message
where status != 2
and from_id = 1
and to_id = #{userId}
and conversation_id = #{topic}
</select>
5.2.9 查询某个用户的未读通知数量,查询某个用户的某个通知事件类型的未读通知数量
对应接口
int selectNoticeUnreadCount(int userId, String topic);
注意事项
对应SQL
<select id="selectNoticeUnreadCount" resultType="int">
select count(id) from message
where status = 0
and from_id = 1
and to_id = #{userId}
<if test="topic!=null">
and conversation_id = #{topic}
</if>
</select>
5.2.10 分页查询某个用户的,某个通知事件类型的通知
对应接口
List<Message> selectNotices(int userId, String topic, int offset, int limit);
注意事项
按照时间降序排序。
对应SQL
<select id="selectNotices" resultType="Message">
select <include refid="selectFields"></include>
from message
where status != 2
and from_id = 1
and to_id = #{userId}
and conversation_id = #{topic}
order by create_time desc
limit #{offset}, #{limit}
</select>