文件变更
本节文件变更如下
创建 post(文章)表
DROP TABLE IF EXISTS `post`;
CREATE TABLE `post` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`author_id` int(11) NOT NULL,
`title` varchar(100) NOT NULL,
`content` text NOT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
Post 类
新增 Post.java
public class Post {
private Integer id;
private User author;
private Integer authorId; // 作者的 id
private String title; // 文章标题
private String content; // 文章内容
private Date createTime;
// ... getter and setter
}
Controller 层
新增 PostApi.java
/**
* 文章接口
*/
@RestController
@RequestMapping("/api/post")
public class PostApi {
private PostService postService;
@Autowired
public PostApi(PostService postService) {
this.postService = postService;
}
@PostMapping("")
@LoginRequired
public Post add(@RequestBody Post post, @CurrentUser User user) {
post.setAuthorId(user.getId());
post = postService.add(post);
return post;
}
@GetMapping("/{id}")
public Object findById(@PathVariable int id) {
Post post = postService.findById(id);
if (post == null) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("message", "文章不存在");
return jsonObject;
} else {
return post;
}
}
}
add
方法用上了前两节写的 @LoginRequired 注解进行登录拦截和 @CurrentUser 注解获取当前登录用户。
Service 层
新增 PostService.java
@Service
public class PostService {
private PostMapper postMapper;
@Autowired
public PostService(PostMapper postMapper) {
this.postMapper = postMapper;
}
@Transactional
public Post add(Post post) {
postMapper.add(post);
return findById(post.getId());
}
public Post findById(Integer id) {
Post param = new Post();
param.setId(id);
return postMapper.findOne(param);
}
}
这里说下 @Transactional
(事务管理)注解,假如这个这个方法里面有多个数据库操作,想要某个操作出错时回滚这个方法里面的所有操作,就在这个方法里面加上这个注解。比如 add
方法,假设第一步添加成功,第二步查询失败,因为有 @Transactional
注解的存在,抛出异常之后数据库也会回滚到未添加时的状态。
Mapper 接口
新增 PostMapper.java
public interface PostMapper {
int add(Post post);
Post findOne(Post param);
}
新增 PostMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.hpm.blog.mapper.PostMapper">
<resultMap id="PostResultMap" type="com.hpm.blog.model.Post" autoMapping="true">
<id column="id" property="id" /> <!-- id 很重要 -->
<!--关联作者,post 表和 user 表可能会用一些字段重复,比如 id 这个属性,所以给 user 表的字段加上columnPrefix(前缀)-->
<association property="author" autoMapping="true" columnPrefix="author__"
javaType="com.hpm.blog.model.User">
<id column="author_id" property="id" />
</association>
</resultMap>
<insert id="add" useGeneratedKeys="true" keyProperty="id">
INSERT INTO post (author_id, title, content) VALUES (#{authorId}, #{title}, #{content});
</insert>
<select id="findOne" resultMap="PostResultMap">
SELECT
post.id,
post.author_id ,
post.title ,
post.content ,
post.create_time ,
post.update_time,
<!-- 作者信息,password 不需要就不查了 -->
`user`.id as author__id,
`user`.`name` as author__name
FROM post
LEFT JOIN `user` ON `user`.id=post.author_id
<where>
<if test="id!=null">
AND post.id=#{id}
</if>
</where>
</select>
</mapper>
查询接口用了关联查询,并且写了个 ResultMap
来映射文章和用户的一对一关系。association
的 columnPrefix
属性在多表查询中特别有用。
测试
重启项目,使用 postman 发送一个 post
请求到 /api/post
不要忘了带上
token
查看项目完整代码
项目地址: https://github.com/hyrijk/spring-boot-blog
克隆项目到本地
git clone https://github.com/hyrijk/spring-boot-blog.git
checkout 到当前版本
git checkout 239b170322e5734a06dde32c1648a3cde53acf8a
完。