紧接着上一篇教程Springboot入门教程(1)
,这一篇我要来说明一下如何在Springboot项目中使用MyBatis来操作数据库,进行增删改查。
预备环境:除了java8以上和IntelliJ IDEA 2019以上之外,需要安装Mysql5.7以上,另外推荐Navicat作为连接数据库的客户端。
先做一下数据库准备,用Navicat连接到本地的数据库服务器,创建一个叫schoolmanager的数据库
在schoolmanager数据库中插入一张subject的表
接着开始修改代码,我们在上一篇创建的Springboot项目schoolmanager的基础上,先把上一篇中在build.gradle中的mybatis和mysql依赖包的注释去掉。
接着需要在项目中配置数据库和mybatis,在resources中的application.properties添加如下配置
spring.datasource.url=jdbc:mysql://localhost:3306/schoolmanager?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.mapper-locations=classpath*:mapper/*.xml
mybatis.type-aliases-package=com.example.schoolmanager.entity
这里要注意的是数据库的名称,连接数据库的用户名和密码。mybatis.mapper-locations表示指向的mybatis的mapper xml文件的存放位置,是在resources/mapper里面。而mybatis.type-aliases-package是存放实体类的包名。
之后我们需要在SchoolmanagerApplication中添加mybatis的mapper接口的包名注释
@SpringBootApplication
@MapperScan("com.example.schoolmanager.mapper")
public class SchoolmanagerApplication {
public static void main(String[] args) {
SpringApplication.run(SchoolmanagerApplication.class, args);
}
}
这里直接添加这个注释后可以指示系统直接去这个包下面找到mapper接口,省去在每个mapper接口中添加注释的麻烦。
然后根据前面配置的,我们需要创建一个entity的package,在entity下面创建一个Subject的实体类,代码如下
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
再创建一个mapper的package,就是对应在SchoolmanagerApplication 里面配置的@MapperScan,在里面新建一个SubjectMapper的接口,代码如下
public interface SubjectMapper {
void insertSubject(@Param("name")String name);
}
这里先写的是一个增加subject数据的接口方法。
根据之前配置的在recources路径下面创建一个mapper的文件夹,在里面创建一个SubjectMapper的xml文件,其中代码如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mappper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.schoolmanager.mapper.SubjectMapper">
<resultMap id="subject" type="com.example.schoolmanager.entity.Subject">
<id property="id" column="id"/>
<result property="name" column="name"/>
</resultMap>
<insert id="insertSubject">
insert into subject (name) values(#{name})
</insert>
</mapper>
这个xml文件很关键,所有数据库操作都是写在这里面的。这里要注意的是这个xml文件的命名和mapper包下面的mapper接口名称必须保持一致,否则有可能运行时找不到对应的xml文件。
这里虽然在namespace中配置了对应的mapper接口,但是还是建议将两者命名一致(笔者之前就遇到了两者没有命名一致导致怎么都报找不到对应xml文件的错误)。
resultMap中,type就是对应的实体类,id是具有唯一标识的字段,一般就是对应数据库中的id,result是其他字段。property对应的是映射到实体类中的参数名称,column是sql语句输出时的列名。
insert标签就是用于插入数据的,id对应的是mapper接口中的方法名,中间就是插入一条数据的sql语句,前面一个name是数据库表中的列名,后面{}里面的name就是mapper接口中@Param的名称。
最后再写controller,在controller包下面新建一个SubjectController类,代码如下
@RestController
@RequestMapping(value = "/subject")
public class SubjectController {
@Autowired
SubjectMapper subjectMapper;
@PostMapping(value = "/addSubject")
public String addSubject(final String name){
subjectMapper.insertSubject(name);
return "Insert success";
}
}
这里给这个类加了一个@RequestMapping,使该类下面接收的请求路径都有"/subject"的前缀。然后这边用到了上一篇教程提到的@PostMapping,接收的是post请求。
到这增的代码就编写完成了,可以启动项目,如果没有报错,就可以测试了。
测试推荐使用postman
这里返回Insert success说明请求成功,用Navicat查看subject表,会发现插入了一条新的数据。
接下来可以把删改查的代码放到一起编写。在这之前,为了让返回的数据格式更规范一些,我们先编写一个类来存放返回的数据。在entity包下新建一个类ResponseData
public class ResponseData {
private final String message;
private final int code;
private final Map<String, Object> data = new HashMap<String, Object>();
public String getMessage() {
return message;
}
public int getCode() {
return code;
}
public Map<String, Object> getData() {
return data;
}
public ResponseData putDataValue(String key, Object value) {
data.put(key, value);
return this;
}
private ResponseData(int code, String message) {
this.code = code;
this.message = message;
}
public static ResponseData ok() {
return new ResponseData(200, "Ok");
}
public static ResponseData notFound() {
return new ResponseData(404, "Not Found");
}
public static ResponseData badRequest() {
return new ResponseData(400, "Bad Request");
}
public static ResponseData forbidden() {
return new ResponseData(403, "Forbidden");
}
public static ResponseData unauthorized() {
return new ResponseData(401, "unauthorized");
}
public static ResponseData serverInternalError() {
return new ResponseData(500, "Server Internal Error");
}
public static ResponseData customerError() {
return new ResponseData(1001, "customer Error");
}
}
在这个类中,我们写了一些常见的返回状态,可以直接调用。
然后才修改SubjectMapper的接口,添加几个方法
public interface SubjectMapper {
void insertSubject(@Param("name")String name);
List<Subject> findSubjects(@Param("name")String name);
void updateSubject(@Param("id")Long id, @Param("name")String name);
void deleteSubject(@Param("id")Long id);
}
再修改SubjectMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mappper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.schoolmanager.mapper.SubjectMapper">
<resultMap id="subject" type="com.example.schoolmanager.entity.Subject">
<id property="id" column="id"/>
<result property="name" column="name"/>
</resultMap>
<insert id="insertSubject">
insert into subject (name) values(#{name})
</insert>
<select id="findSubjects" resultType="com.example.schoolmanager.entity.Subject" >
select id,name from subject where name like CONCAT('%',#{name},'%')
</select>
<update id="updateSubject">
update subject
<set>
<if test="name != ''">name = #{name}</if>
</set>
where id = #{id}
</update>
<delete id="deleteSubject">
delete from subject where id = #{id}
</delete>
</mapper>
这里查的时候包含了按name进行模糊查询的功能,update的时候加了判断name是否为空。
最后修改SubjectController
@RestController
@RequestMapping(value = "/subject")
public class SubjectController {
@Autowired
SubjectMapper subjectMapper;
@PostMapping(value = "/addSubject")
public ResponseData addSubject(final String name){
subjectMapper.insertSubject(name);
ResponseData responseData = ResponseData.ok();
return responseData;
}
@RequestMapping(value = "/subjects")
public ResponseData findSubjects(final String name){
List<Subject> subjectList = subjectMapper.findSubjects(name);
ResponseData responseData = ResponseData.ok();
responseData.putDataValue("subjects", subjectList);
return responseData;
}
@PostMapping(value = "/editSubject")
@ResponseBody
public ResponseData editSubject(Long id, final String name)
{
subjectMapper.updateSubject(id, name);
ResponseData responseData = ResponseData.ok();
return responseData;
}
@PostMapping(value = "/deleteSubject")
@ResponseBody
public ResponseData deleteSubject(Long id)
{
subjectMapper.deleteSubject(id);
ResponseData responseData = ResponseData.ok();
return responseData;
}
}
全部编写完成后启动项目,用postman测试。
本篇教程中的代码可以参考我在github上面的代码https://github.com/ahuadoreen/studentmanager,因为github上的代码是之前已经写好的完整版本,所以Springboot的版本号和项目名称和文中使用的不同,其余思路是一致的,可供参考使用。
补充说明:如果之前有用ssh或者ssm框架开发java web经验的可能会想,我这里的代码为什么没有service层呢。其实这是因为考虑到这是一个demo性质的项目,只是单纯的增删改查,没有复杂的业务逻辑,所以省略了service层。如果是复杂的大型项目,那么还是需要增加service层的。