緊接著上一篇教程Springboot入門教程(1)
,這一篇我要來說明一下如何在Springboot項(xiàng)目中使用MyBatis來操作數(shù)據(jù)庫,進(jìn)行增刪改查。
預(yù)備環(huán)境:除了java8以上和IntelliJ IDEA 2019以上之外,需要安裝Mysql5.7以上,另外推薦Navicat作為連接數(shù)據(jù)庫的客戶端。
先做一下數(shù)據(jù)庫準(zhǔn)備,用Navicat連接到本地的數(shù)據(jù)庫服務(wù)器,創(chuàng)建一個(gè)叫schoolmanager的數(shù)據(jù)庫

在schoolmanager數(shù)據(jù)庫中插入一張subject的表

接著開始修改代碼,我們?cè)谏弦黄獎(jiǎng)?chuàng)建的Springboot項(xiàng)目schoolmanager的基礎(chǔ)上,先把上一篇中在build.gradle中的mybatis和mysql依賴包的注釋去掉。

接著需要在項(xiàng)目中配置數(shù)據(jù)庫和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
這里要注意的是數(shù)據(jù)庫的名稱,連接數(shù)據(jù)庫的用戶名和密碼。mybatis.mapper-locations表示指向的mybatis的mapper xml文件的存放位置,是在resources/mapper里面。而mybatis.type-aliases-package是存放實(shí)體類的包名。
之后我們需要在SchoolmanagerApplication中添加mybatis的mapper接口的包名注釋
@SpringBootApplication
@MapperScan("com.example.schoolmanager.mapper")
public class SchoolmanagerApplication {
public static void main(String[] args) {
SpringApplication.run(SchoolmanagerApplication.class, args);
}
}
這里直接添加這個(gè)注釋后可以指示系統(tǒng)直接去這個(gè)包下面找到mapper接口,省去在每個(gè)mapper接口中添加注釋的麻煩。
然后根據(jù)前面配置的,我們需要?jiǎng)?chuàng)建一個(gè)entity的package,在entity下面創(chuàng)建一個(gè)Subject的實(shí)體類,代碼如下
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;
}
再創(chuàng)建一個(gè)mapper的package,就是對(duì)應(yīng)在SchoolmanagerApplication 里面配置的@MapperScan,在里面新建一個(gè)SubjectMapper的接口,代碼如下
public interface SubjectMapper {
void insertSubject(@Param("name")String name);
}
這里先寫的是一個(gè)增加subject數(shù)據(jù)的接口方法。
根據(jù)之前配置的在recources路徑下面創(chuàng)建一個(gè)mapper的文件夾,在里面創(chuàng)建一個(gè)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>
這個(gè)xml文件很關(guān)鍵,所有數(shù)據(jù)庫操作都是寫在這里面的。這里要注意的是這個(gè)xml文件的命名和mapper包下面的mapper接口名稱必須保持一致,否則有可能運(yùn)行時(shí)找不到對(duì)應(yīng)的xml文件。
這里雖然在namespace中配置了對(duì)應(yīng)的mapper接口,但是還是建議將兩者命名一致(筆者之前就遇到了兩者沒有命名一致導(dǎo)致怎么都報(bào)找不到對(duì)應(yīng)xml文件的錯(cuò)誤)。
resultMap中,type就是對(duì)應(yīng)的實(shí)體類,id是具有唯一標(biāo)識(shí)的字段,一般就是對(duì)應(yīng)數(shù)據(jù)庫中的id,result是其他字段。property對(duì)應(yīng)的是映射到實(shí)體類中的參數(shù)名稱,column是sql語句輸出時(shí)的列名。
insert標(biāo)簽就是用于插入數(shù)據(jù)的,id對(duì)應(yīng)的是mapper接口中的方法名,中間就是插入一條數(shù)據(jù)的sql語句,前面一個(gè)name是數(shù)據(jù)庫表中的列名,后面{}里面的name就是mapper接口中@Param的名稱。
最后再寫controller,在controller包下面新建一個(gè)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";
}
}
這里給這個(gè)類加了一個(gè)@RequestMapping,使該類下面接收的請(qǐng)求路徑都有"/subject"的前綴。然后這邊用到了上一篇教程提到的@PostMapping,接收的是post請(qǐng)求。
到這增的代碼就編寫完成了,可以啟動(dòng)項(xiàng)目,如果沒有報(bào)錯(cuò),就可以測試了。
測試推薦使用postman

這里返回Insert success說明請(qǐng)求成功,用Navicat查看subject表,會(huì)發(fā)現(xiàn)插入了一條新的數(shù)據(jù)。
接下來可以把刪改查的代碼放到一起編寫。在這之前,為了讓返回的數(shù)據(jù)格式更規(guī)范一些,我們先編寫一個(gè)類來存放返回的數(shù)據(jù)。在entity包下新建一個(gè)類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");
}
}
在這個(gè)類中,我們寫了一些常見的返回狀態(tài),可以直接調(diào)用。
然后才修改SubjectMapper的接口,添加幾個(gè)方法
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>
這里查的時(shí)候包含了按name進(jìn)行模糊查詢的功能,update的時(shí)候加了判斷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;
}
}
全部編寫完成后啟動(dòng)項(xiàng)目,用postman測試。
本篇教程中的代碼可以參考我在github上面的代碼https://github.com/ahuadoreen/studentmanager,因?yàn)間ithub上的代碼是之前已經(jīng)寫好的完整版本,所以Springboot的版本號(hào)和項(xiàng)目名稱和文中使用的不同,其余思路是一致的,可供參考使用。
補(bǔ)充說明:如果之前有用ssh或者ssm框架開發(fā)java web經(jīng)驗(yàn)的可能會(huì)想,我這里的代碼為什么沒有service層呢。其實(shí)這是因?yàn)榭紤]到這是一個(gè)demo性質(zhì)的項(xiàng)目,只是單純的增刪改查,沒有復(fù)雜的業(yè)務(wù)邏輯,所以省略了service層。如果是復(fù)雜的大型項(xiàng)目,那么還是需要增加service層的。