做爲一個前端開發者和僞後臺開發者先後端的技術都須要瞭解一些。早些時候作Java開發的時候主要用到的是SSH框架,對於SSM瞭解不是不少。以前的博客中寫了一些關於springboot的總結,深深地被springboot的簡化配置吸引,最近出差有時間繼續完善一下springboot系列。以前提到了springboot的helloworld的建立、三層架構的搭建、spring security的應用。上面三個掌握了以後就能夠搭建一個簡單springboot開發框架,用來練手是很不錯的。如今咱們進行逐個細化,這裏的細化不是說教技術點,而是根據開發需求來,用到什麼說什麼。先從ORM框架Mybatis提及吧。
很簡單,打開dos,使用spring init命令建立一個springboot項目。以下:前端
$ spring init -g=com.briup.apps -a=app03 -d=mybatis,mysql app03 $ cd app03 $ mvn install
上面意思表示maven項目的組ID爲com.briup.apps ,artifactID爲app03,依賴mybatis和mysql驅動,項目名稱爲app03。項目建立完成後進入到app03目錄下,爲app03安裝所須要的依賴
這樣,就建立了一個app03的項目,而後經過eclipse打開該項目便可。java
這時候若是直接運行項目,將會報錯,提示數據源配置出錯。這個問題在搭建三層架構的章節中提到過,解決方案是在application.properties文件中添加以下配置mysql
#數據源相關參數的配置 spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/poll2.0 spring.datasource.username=root spring.datasource.password=root #mybatis映射地址的位置 mybatis.mapper-locations= classpath:/mapper/**/*.xml
在常見的數據模型中,一對多關係和多對多關係是最爲經常使用的關係,因此我這裏測試採用的案例是大學《數據庫系統概論》 教程中的案例,班級,學生,課程之間的關係,具體以下圖:spring
根據如上ER圖,建表sql
-- ---------------------------- -- Table structure for tbl_clazz -- ---------------------------- DROP TABLE IF EXISTS `tbl_clazz`; CREATE TABLE `tbl_clazz` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for tbl_course -- ---------------------------- DROP TABLE IF EXISTS `tbl_course`; CREATE TABLE `tbl_course` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `credit` int(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for tbl_sc -- ---------------------------- DROP TABLE IF EXISTS `tbl_sc`; CREATE TABLE `tbl_sc` ( `id` int(11) NOT NULL AUTO_INCREMENT, `student_id` int(11) DEFAULT NULL, `course_id` int(11) DEFAULT NULL, `score` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `student_id` (`student_id`), KEY `course_id` (`course_id`), CONSTRAINT `tbl_sc_ibfk_1` FOREIGN KEY (`student_id`) REFERENCES `tbl_student` (`id`) ON DELETE SET NULL, CONSTRAINT `tbl_sc_ibfk_2` FOREIGN KEY (`course_id`) REFERENCES `tbl_course` (`id`) ON DELETE SET NULL ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for tbl_student -- ---------------------------- DROP TABLE IF EXISTS `tbl_student`; CREATE TABLE `tbl_student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `gender` varchar(255) DEFAULT NULL, `clazz_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `clazz_id` (`clazz_id`), CONSTRAINT `tbl_student_ibfk_1` FOREIGN KEY (`clazz_id`) REFERENCES `tbl_clazz` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
搭建項目結構,而且根據表結構建立類數據庫
由於是對mybatis的學習,因此這裏我重點寫了bean和dao,也就是對於數據訪問層的剖析測試。json
//班級類 public class Clazz { private Long id; private String name; //對應的setters,getters } //課程類 public class Course { private Long id; private String name; private Integer credit; //對應的setters,getters } //學生類 public class Student { private Long id; private String name; private String gender; private Long clazz_id; //對應的setters,getters } //學生選課類 public class StudentCourse { private Long id; private Long student_id; private Long course_id; //對應的setters,getters }
在mybatis中,咱們只須要提供映射接口和映射文件便可,而事務的處理和SqlSession的處理咱們交給springBoot便可,這種方式能夠使得咱們很快的構建數據訪問層的代碼。後端
package com.briup.apps.app03.dao; import java.util.List; import com.briup.apps.app03.bean.Student; public interface StudentMapper { List<Student> findAll(); Student findById(long id); void save(Student student); void update(Student student); void deleteById(long id); }
查看mybatis官方網站能夠知道,實現增刪改查須要在xml中提供對應的select,insert,update,delete元素,id名稱與映射接口中定義的方法名稱相同,resultType屬性表示返回值類型,parameterType表示參數類型。還有更多其餘屬性的解釋能夠參照官方文檔springboot
<?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.briup.apps.app03.dao.StudentMapper"> <!-- 查詢全部學生 --> <select id="findAll" resultType="com.briup.apps.app03.bean.Student"> select * from tbl_student </select> <!-- 經過ID查詢學生信息 --> <select id="findById" resultType="com.briup.apps.app03.bean.Student"> select * from tbl_student where id = #{id} </select> <!-- 保存學生信息 --> <insert id="save" parameterType="com.briup.apps.app03.bean.Student"> insert into tbl_student values(null,#{name},#{gender},#{clazz_id}) </insert> <!-- 修改學生信息 --> <update id="update" parameterType="com.briup.apps.app03.bean.Student"> update tbl_student set name = #{name}, gender = #{gender} ,clazz_id = #{clazz_id} where id = #{id} </update> <!-- 經過id刪除學生信息 --> <delete id="deleteById" parameterType="long"> delete from tbl_student where id = #{id} </delete> </mapper>
不少時候單表的增刪改查並不能知足項目需求,好比,在查詢學生信息的時候咱們不單單須要拿到clazz_id這個外鍵,咱們還須要知道該學生所在的班級名稱,這樣就須要用到多表查詢。
一個學生對應一個班級,爲了可以映射查詢結構,這裏咱們須要先從新定義一個POJO類,來表示這種多對一關係。
以下:mybatis
package com.briup.apps.app03.bean.vm; import com.briup.apps.app03.bean.Clazz; import com.briup.apps.app03.bean.Student; public class StudentVM { //學生信息 private Student student; //學生對應的班級信息 private Clazz clazz; //setters getters }
package com.briup.apps.app03.dao.extend; import java.util.List; import com.briup.apps.app03.bean.vm.StudentVM; public interface StudentVMMapper { List<StudentVM> findAll(); }
<?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.briup.apps.app03.dao.extend.StudentVMMapper"> <!-- 查詢全部學生 --> <select id="findAll" resultMap="studentVMResultType"> select s.id as s_id, s.name as s_name, s.gender, c.id as c_id, c.name as c_name from tbl_student as s ,tbl_clazz as c where s.clazz_id = c.id </select> <resultMap type="com.briup.apps.app03.bean.vm.StudentVM" id="studentVMResultType"> <association property="student" javaType="com.briup.apps.app03.bean.Student"> <id column="s_id" property="id"/> <result column="s_name" property="name"/> <result column="gender" property="gender"/> </association> <association property="clazz" javaType="com.briup.apps.app03.bean.Clazz"> <id column="c_id" property="id"/> <result column="c_name" property="name"/> </association> </resultMap> </mapper>
這種狀況下映射文件還有另一種寫法:
<?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.briup.apps.app03.dao.extend.StudentVMMapper"> <!-- 查詢全部學生 --> <select id="findAll" resultMap="studentVMResultType"> select * from tbl_student </select> <resultMap type="com.briup.apps.app03.bean.vm.StudentVM" id="studentVMResultType"> <association property="student" column="id" javaType="com.briup.apps.app03.bean.Student" select="com.briup.apps.app03.dao.StudentMapper.findById" ></association> <association property="clazz" column="clazz_id" javaType="com.briup.apps.app03.bean.Clazz" select="com.briup.apps.app03.dao.ClazzMapper.findById"></association> </resultMap> </mapper>
在開發過程當中咱們還常常遇到一對多的查詢,好比,查詢題目的時候須要查詢該題目下的全部選項的信息,查詢班級的時候級聯查詢出該班級下全部的學生信息。
pojo類
package com.briup.apps.app03.bean.vm; import java.util.List; import com.briup.apps.app03.bean.Student; public class ClazzVM { private Long id; private String name; private List<Student> students; //setters getters }
映射接口
package com.briup.apps.app03.dao.extend; import com.briup.apps.app03.bean.vm.ClazzVM; public interface ClazzVMMapper { ClazzVM findById(long id); }
映射文件
<?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.briup.apps.app03.dao.extend.ClazzVMMapper"> <!-- 查詢全部班級以及該班級下全部學生 --> <select id="findById" resultMap="clazzVMResultType"> select * from tbl_clazz where id = #{id} </select> <resultMap type="com.briup.apps.app03.bean.vm.ClazzVM" id="clazzVMResultType"> <id column="id" property="id"/> <result column="name" property="name"/> <collection property="students" column="id" javaType="ArrayList" ofType="com.briup.apps.app03.bean.Student" select="com.briup.apps.app03.dao.StudentMapper.findByClazzId"></collection> </resultMap> </mapper>
這裏的測試我使用的是springboot的單元測試功能,以下
package com.briup.apps.app03.test; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import com.briup.apps.app03.bean.Student; import com.briup.apps.app03.bean.vm.StudentVM; import com.briup.apps.app03.dao.StudentMapper; import com.briup.apps.app03.dao.extend.StudentVMMapper; import net.minidev.json.JSONArray; @RunWith(SpringRunner.class) @SpringBootTest public class StudentMapperTest { @Autowired private StudentMapper studentMapper; @Autowired private StudentVMMapper studentVMMapper; //@Test public void save(){ Student student = new Student(); student.setName("張三"); student.setGender("男"); studentMapper.save(student); System.out.println("--保存成功"); } //@Test public void update(){ Student student = new Student(); student.setId(8L); student.setName("張三三"); student.setGender("男"); studentMapper.update(student); System.out.println("--修改爲功"); } //@Test public void delete(){ studentMapper.deleteById(8L); System.out.println("--刪除成功"); } @Test public void test1(){ List<Student> list = studentMapper.findAll(); String json = JSONArray.toJSONString(list); System.out.println("student:"+json); } @Test public void test2(){ List<StudentVM> list = studentVMMapper.findAll(); String json = JSONArray.toJSONString(list); System.out.println("studentVM:"+json); } }
爲了使得代碼拓展性強一些,我將單表操做的類和關聯操做的類分開存放。爲了實現敏捷開發,咱們能夠使用mybatis generator來實現單表操做的pojo類,映射文件,映射接口的自動產生。