讲自己项目的时候每个技术点讲设计的原因
一些小问题
- 数据库中Longint对应java中long类型
- Byte数据类型先转Integer,比较好处理,每次重新generator都要记得改
- mybatis generator多次使用容易重复创建,删掉xml文件重新generator即可
- controller层一般做不侵入业务逻辑的工作,一般是入口,不能相互调用。因此对于涉及到几张表操作的一个功能,例如用户注册要在user、role、relationship中添加数据,则统一在service层完成,service可用互相调用
- 在设计表格的时候,若mysql中数据类型为tinyint,长度为1,则generator生成model的类型是boolean的
- 返回给前端的时候不要直接返回数据库生成的model,最好拼接一个viewModel,因为直接返回model会是明文,很容易猜到语句,容易被SQL注入
- mybaits获取mysql的text类型返回null,原因是因为查询方法中selectByExample是不会带上有text类型的数据,要用selectByExampleWithBLOBs方法。原因是由于mapper以及xml文件这些都是用mybatis generator生成的,text类型的数据原来能够选择不查询。
- 给前端返回view model的时候,返回的东西前端应该不用再去做类似参数转换的东西,比如数据库里面存的是时间戳,那么返回给前端的时候,就转换成真正的时间,类型转换为String这样,前端拿到后就不用再做参数转换了。尽量避免前端做额外的事情
- 关于数据库索引的极左原则,项目中有
select from where accountName = XXX and userPassword = xxx
这样的查询,那么我应该为user表中accountName和userPassword者两个字段建立联合索引,而不是单独为accountName和userPassword分别建立索引。因为根据极左原则,如果对 A.a A.b 三个字段添加联合索引,则只要在where中出现了A.a,就会启动此索引。XXXX where A.b and A.c
这样会只用到A.b的索引,A.c的不会用到
Shiro保持用户登录状态的构想和设计
登录成功后返回一个token,下次登录时携带这个token就行了
关于ViewModel
可专门建立一个view model来建立一个用于展示和redis存储的model,方便后续操作
另一个理由是redis只存热点数据、所以拼接view层的操作提前放在了这里
@Override
public List<CompetitionView> findByCompeTypeAndCompeSeason(Integer compeType, Integer season) {
//先查redis
String jsonKey = compeType+","+season+"_competitionsList";
String jsonString = (String)redisUtils.get(jsonKey);
List<CompetitionView> list = JSONObject.parseArray(jsonString,CompetitionView.class);
if(list!=null){
System.out.println("直接从人redis");
return list;
}
//redis中没有,查数据库
CompetitionExample competitionExample = new CompetitionExample();
//int转byte
competitionExample.createCriteria().andIsEnableEqualTo((byte)1).andCompeTypeEqualTo(compeType).andCompeSeasonEqualTo(season);
List<Competition> competitionList = competitionMapper.selectByExample(competitionExample);
//存redis
List<CompetitionView> redisIn = new ArrayList<>();
//存热点数据
for(int i=0;i< competitionList.size();i++){
CompetitionView competitionView = new CompetitionView();
competitionView.setCompetitionId(competitionList.get(i).getCompeId()+"");//赛事主键 id
competitionView.setCompetitonTime(competitionList.get(i).getCompeTime()+"");//赛事时间
competitionView.setCompetitionStatus(competitionList.get(i).getCompeStatus()+"");//赛事状态
competitionView.setCompetitionHtId(competitionList.get(i).getCompeHtId()+"");//主队 team id
competitionView.setCompetitionGtId(competitionList.get(i).getCompeGtId()+"");//客队 team id
competitionView.setCompetitionHtScore(competitionList.get(i).getCompeHostScore()+""