数据库设计如下:
任务:开发社区首页,显示前十个帖子;开发分页组件,分页显示所有帖子。
开发流程:entity->dao->mapper.xml->service->controller
由于关注后端,所以未使用前后分离且记录过程关注后端
(1)创建DiscussPost实体类;
即帖子实体类。
(2)创建DiscussPostMapper接口;
/**
* 分页查询帖子
*
* @param userId
* @param offset 每一页 起始行的行号
* @param limit
* orderMode 如果传入1按照热度来排
* @return
*/
List<DiscussPost> selectDiscussPosts(
@Param("userId") int userId,
@Param("offset") int offset,
@Param("limit") int limit);
/**
* 查询用户的帖子 @Param注解用于给定参数取别名
* 如果需要动态拼接SQL:即 只有一个参数+在<if></if>里面使用,则必须加别名
*
* @param userId
* @return
*/
int selectDiscussPostRows(@Param("userId") int userId);
selectDiscussPosts(int userId, int offset, int limit)方法的userId参数是为了方便按用户id查询该用户发的帖子,正常使用是用不到userId,所以后面写sql用动态sql选择性的添加userId,offset是每页起始行行号,limit是每页最多显示多少数据。
int selectDiscussPostRows(@Param(“userId”) int userId)是查询一共多少行,这里的参数userId和前一个方法一样,写sql语句用动态sql,另外,如果方法只有一个参数,并且在动态sql的if里使用,则参数前必须加@Param起别名
(3)编写discusspost-mapper.xml
<sql id="selectFields">
id,user_id,title,content,type,status,create_time,comment_count,score
</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>
order by type desc,create_time desc
limit #{offset},#{limit}
</select>
<select id="selectDiscussPostRows" resultType="int">
select count(id)
from discuss_post
where status !=2
<if test="userId!=0">
and user_id = #{userId}
</if>
</select>
当返回类型为List<自定义类型>时,requestType=“自定义类型”,list是java自带的可以解析出来,不用声明;
order by type desc, create_time desc是优先按类型倒序排序,类型相同按照产生时间倒序排序;
limit #{offset}, #{limit} 是分页,offset是每页起始行行号,limit是每页最多显示多少数据;
(4)编写DiscussPostService
@Service
public class DiscussPostService {
@Autowired
private DiscussPostMapper discussPostMapper;
public List<DiscussPost> findDiscussPosts(int userId,int offset,int limit){
return discussPostMapper.selectDiscussPosts(userId,offset,limit);
}
public int findDiscussPostRows(int userId){
return discussPostMapper.selectDiscussPostRows(userId);
}
}
虽然能容基本重复,但不能COntroller 直接调用DAO 以防业务扩展、 跨层调用涉及到安全性问题。
(5)编写HomeController
public class HomeController {
@Autowired
private UserService userService;
@Autowired
private DiscussPostService discussPostService;
@RequestMapping(path = "/index",method = RequestMethod.GET)
public String getIndexPage(Model model, Page page){
//方法调用前 SpringMVC 会自动实例化Model和Page 并将Page注入Model
//所以在thyeleaf中可以直接访问page的数据
page.setRows(discussPostService.findDiscussPostRows(0));
page.setPath("/index");
List<DiscussPost> list = discussPostService.findDiscussPosts(0, page.getOffset(), page.getLimit()) ;
List<Map<String,Object>> discussPosts = new ArrayList<>();
if(list != null){
for(DiscussPost eachPost :list){
Map<String,Object> map = new HashMap<>();
map.put("post",eachPost);
User user = userService.findUserById(eachPost.getUserId());
map.put("user",user);
discussPosts.add(map);
}
}
model.addAttribute("discussPosts",discussPosts);
return "/index";
}
}
方法在调用前,springmvc会自动实例化model和page,同时会把page注入到model中,因此后面可以不用向model中使用addAttribute添加page。
userid为外键,但查询到的帖子后要显示用户名,该如何操作?
- 直接在在SQL关联查询用户表,获取username
- 单独得到userid后 再去调用方法查询 username 而后组合在一起
选择后者 :使用redis 性能会高 代码清晰 好修改