1.好友表的设计
相关实体:
1.用户
2.好友实体之间的关系:
一对一: 一个用户,只能有一个好友,一个好友也只能被一个用户进行添加(错误)一对多:一个用户,可以有多个好友.一个好友也只能被一个用户进行添加(错误)
多对多: 一个用户,可以有多个好友.一个好友也可以被多个用户添加
此处需要有一个关联表,通过关联表把另处两个表给联系到一起~~【此处准确来说,是把一个表(用户表) 里的两条数据,给联系到一起】
【两个表: 用户表,好友表..(好友,也是用户~~) 其实是一张表.】
两个重要的问题
1.如果用户很多,每个用户的好友很很多,这个表就会非常大.咋办?假设你的聊天程序,有一亿用户,平均每个用户有 100 个好友
此时这个表里的数据量, 100 亿【如何处理?分库分表!!
典型的思路: 以 userld 进行切分比如针对 userld 来计算一个 hashcode(计算 hashcode 有很多种方式,大家不必局限于 JDK 里面那个比较土的计算方式)
然后再针对 hashcode 进行切分~假设分成 100 张表(编号 friend0-friend99)此时,同一个 userld 的记录,一定在同一张表里~~
后续比如需要查询某个用户,都有哪些好友,还是按照同样的办法来查还是先把 userld 按照同样的算法, 算 hashcode.算出来之后,还是进行 % 100 =>结果是几,就去第几个表里进行査询】2.在分库分表的背景下,当前是希望,每个表大小是相对均匀的,
但是在用户中,可能会存在大V!! 由于大V的好友特别特别多,就可能直接导致分表的结果并不均衡了。 怎么办??
具体问题,具体分析;特殊情况, 特殊处理.【大 V 是属于及其少数的用户,
可以针对 大V的 userld,单独分表 (用一个特殊的表,记录下当前有哪些 userid,属于 大 V!!) 再使用专门的表 来保存大V 的好友关系.让大V的表和普通用户的表分开
冷热数据分环处理】
2.设定前后端接口
让客户端从服务器中获取好友列表
3.后端代码
3.1 sql的设计
-- 好友表
drop table if exists friend;
CREATE TABLE friend (`userId` int ,`friendId` int);
-- 表⽰⽤⼾ 1 的好友有 2 和 3. 2 的好友有 1, 3 的好友有 1
insert into friend values(1, 2);
insert into friend values(1, 3);
insert into friend values(2, 1);
insert into friend values(3, 1);
3.2 MODEL
@Data
public class Friend {
private Integer friendId;
private String friendName;
}
3.2 MAPPER
@Mapper
public interface FriendMapper {
//运用子查询
@Select("select userId as friendId,username as friendName from user where userId in (select friendId from friend where userId=#{userId})")
List<Friend> selectFriendByUserId(Integer userId);
}
3.3 SERVICE
@Service
public class FriendService {
@Autowired
private FriendMapper friendMapper;
public List<Friend> getFriendMes(Integer userId){
return friendMapper.selectFriendByUserId(userId);
}
}
3.4 CONTROLLER
@RestController
@RequestMapping("/friend")
public class FriendController {
@Autowired
private FriendService friendService;
@RequestMapping("/getInfo")
public Result getFriendMes(HttpSession httpSession){
User user=(User) httpSession.getAttribute(Constant.USERINFO_SESSION_KEY);
Integer userId=user.getUserId();
List<Friend> friends=friendService.getFriendMes(userId);
return Result.success(friends);
}
}
3.5 POSTMAN测试
4.前端代码
<!-- 好友列表 -->
<!-- class后面写hide就是隐藏了该界面 -->
<!-- 如何实现标签页的切换 -->
<!-- 需要引入js -->
<ul class="list hide" id="friend-list">
<li>
<h4>lisi</h4>
</li>
<li>
<h4>lisi</h4>
</li>
<li>
<h4>lisi</h4>
</li>
<li>
<h4>lisi</h4>
</li>
<li>
<h4>lisi</h4>
</li>
</ul>
function getFriendList() {
$.ajax({
type: 'get',
url: '/friend/getInfo',
success: function(result) {
body=result.data;
// 1. 先把之前的好友列表的内容, 给清空
//不清空会出现问题
let friendListUL = document.querySelector('#friend-list');
friendListUL.innerHTML = '';
// 2. 遍历 body, 把服务器响应的结果, 加回到当前的 friend-list 中.
for (let friend of body) {
let li = document.createElement('li');
li.innerHTML = '<h4>' + friend.friendName + '</h4>';
// 记录id的方式
// 此处把 friendId 也记录下来, 以备后用.
// 把 friendId 作为一个 html 的自定义属性, 加到 li 标签上就行了.
li.setAttribute('friend-id', friend.friendId);
friendListUL.appendChild(li);
// 每个 li 标签, 就对应界面上的一个好友的选项. 给这个 li 加上点击事件的处理.
li.onclick = function() {
// 参数表示区分了当前用户点击的是哪个好友.
clickFriend(friend);
}
}
},
error: function() {
console.log('获取好友列表失败!');
}
});
}
getFriendList();