一、使用註解開發
1、面向接口編程的概念
大家之前都學過面向對象編程,也學習過接口,但在真正的開發中,很多時候我們會選擇面向接口編程
- 根本原因 : 解耦 , 可拓展 , 提高複用 , 分層開發中 , 上層不用管具體的實現 , 大家都遵守共同的標準 , 使得開發變得容易 , 規範性更好。
- 在一個面向對象的系統中,系統的各種功能是由許許多多的不同對象協作完成的。在這種情況下,各個對象內部是如何實現自己的,對系統設計人員來講就不那麼重要了。
- 各個對象之間的協作關係則成爲系統設計的關鍵。小到不同類之間的通信,大到各模塊之間的交互,在系統設計之初都是要着重考慮的,這也是系統設計的主要工作內容。面向接口編程就是指按照這種思想來編程。
關於接口的理解
- 接口從更深層次的理解,應是定義(規範,約束)與實現(名實分離的原則)的分離。
- 接口的本身反映了系統設計人員對系統的抽象理解。
接口應有兩類:
- 第一類是對一個個體的抽象,它可對應爲一個抽象體(abstract class);
- 第二類是對一個個體某一方面的抽象,即形成一個抽象面(interface);
- 一個體有可能有多個抽象面。抽象體與抽象面是有區別的。
三個面向區別
- 面向對象是指,我們考慮問題時,以對象爲單位,考慮它的屬性及方法 。
- 面向過程是指,我們考慮問題時,以一個具體的流程(事務過程)爲單位,考慮它的實現 。
- 接口設計與非接口設計是針對複用技術而言的,與面向對象(過程)不是一個問題.更多的體現就是對系統整體的架構。
2、使用註解開發
步驟:
- 編寫mapping層接口:這次我們不再去編寫接口的
.xml
配置文件,而是直接在接口中使用註解去編寫我們的SQL
代碼。
package com.zyh.mapping;
import com.zyh.pojo.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 使用註解進行開發
*/
public interface UserMapper {
@Select("select * from user")
List<User> getUsers();
}
- 將接口綁定到
mybatis-config.xml
核心配置文件中。
<!--綁定接口-->
<mappers>
<mapper class="com.zyh.mapping.UserMapper"/>
</mappers>
測試:
MyBatis 註解的本質:反射
底層原理:動態代理
3、使用註解完成CRUD操作
接口:
package com.zyh.mapping;
import com.zyh.pojo.User;
import org.apache.ibatis.annotations.*;
import javax.naming.Name;
import java.util.List;
/**
* 使用註解進行開發
*/
public interface UserMapper {
//查詢用戶信息
@Select("select * from user")
List<User> getUsers();
//通過指定參數查詢用戶信息
@Select("select * from mybatis.user where id=#{id} and name=#{name}")
User getUserById(@Param("id") int id,@Param("name") String name);
//插入用戶信息
@Insert("insert into user(id,name,pwd) values (#{id},#{name},#{pwd})")
int addUser(User user);
//修改用戶信息
@Update("update user set name=#{name},pwd=#{pwd} where id=#{id}")
int updateuser(@Param("id") int id,@Param("name") String name,@Param("pwd") String pwd);
//刪除用戶信息
@Delete("delete from user where id=#{id}")
int deleteUser(@Param("id") int id);
}
注意:一定要把UserMapper
接口註冊到Mybatis-Config.xml
核心配置文件中。
測試:
import com.zyh.mapping.UserMapper;
import com.zyh.pojo.User;
import com.zyh.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.testng.annotations.Test;
import java.util.List;
public class UserMapperTest {
@Test
public void test(){
SqlSession session = MyBatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.getUsers();
for (User user : users) {
System.out.println(user);
}
session.close();
}
@Test
public void test1(){
SqlSession session = MyBatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.getUserById(1,"張三");
System.out.println(user);
session.close();
}
@Test
public void test2(){
SqlSession session = MyBatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
int i = mapper.addUser(new User(5, "趙高", "123456"));
if (i > 0) {
System.out.println("查插入用戶數據成功");
}
session.close();
}
@Test
public void test3() {
SqlSession session = MyBatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
int i = mapper.updateuser(5, "小川", "11235813");
if (i > 0) {
System.out.println("修改成功!");
}
session.close();
}
@Test
public void test4() {
SqlSession session = MyBatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
int i = mapper.deleteUser(5);
if (i > 0) {
System.out.println("刪除成功!");
}
session.close();
}
}
二、MyBatis 的執行流程
三、多對一、一對多的ResultMap
假如現在有一個老師和五個學生,站在老師的角度看,老師只有一個,但他的學生卻有許多,這就像一對多,但站在學生的角度看,他們有許多學生,但卻只有一位老師,這就像多對一。 多對一和一對多這個問題要看你從哪個角度分析,不同的角度分析的結果也是不同的。
- 對於學生而言就是關聯 association 多個學生關聯一個老師。
- 對於老師而言就是 集合 connection 一個老師有許多學生,當做一個集合。
準備數據庫:
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老師');
CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小紅', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小張', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');
創建每個表對應的實體類:
//學生類
package com.zyh.pojo;
import lombok.Data;
@Data
public class Student {
private int id;
private String name;
private Teacher teacher;
}
//老師類
package com.zyh.pojo;
import lombok.Data;
@Data
public class Teacher {
private int id;
private String name;
}
每個實體類的接口:
// StudentMapper
package com.zyh.mapping;
import com.zyh.pojo.Student;
import java.util.List;
public interface StudentMapper {
}
//TeacherMapper
package com.zyh.mapping;
public interface TeacherMapper {
List<Student> getStudnts();
}
給兩個接口的分別編寫XML配置:
多對一案例:關聯 assocation
學生StudentMapper.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">
<!--namespace的作用:和你編寫的持久層的接口關聯起來-->
<mapper namespace="com.zyh.mapping.StudentMapper">
<resultMap id="StudentTeacher" type="Student">
<!--property對應實體類的屬性 column對應數據庫的字段名-->
<id property="id" column="sid"/>
<result property="name" column="sname" />
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
<result property="id" column="tid"/>
</association>
</resultMap>
<select id="getStudents" resultMap="StudentTeacher">
select s.id sid,s.name sname,t.name tname,t.id tid
from student s,teacher t
where s.tid = t.id
</select>
</mapper>
測試:
package com.zyh.mapping;
import com.zyh.pojo.Student;
import com.zyh.utils.MyBatisUtils;
import org.junit.jupiter.api.Test;
import java.util.List;
public class StudentMapperTest {
@Test
public void test(){
StudentMapper mapper = MyBatisUtils.getSession().getMapper(StudentMapper.class);
List<Student> students = mapper.getStudents();
for (Student student : students) {
System.out.println(student);
}
}
}
執行結果:
一對多案例:集合collection
Teacher.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">
<!--namespace的作用:和你編寫的持久層的接口關聯起來-->
<mapper namespace="com.zyh.mapping.TeacherMapper">
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="id"/>
<result property="name" column="tname"/>
<!--一對多就是包含關係:collection ofType表示這個屬性的Java類型是什麼-->
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid, s.name sname,t.id id,t.name tname
from student s,teacher t
where s.tid=t.id and t.id=#{id};
</select>
</mapper>
測試:
package com.zyh.mapping;
import com.zyh.pojo.Teacher;
import com.zyh.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;
public class TeacherMapperTest {
@Test
public void test(){
SqlSession session = MyBatisUtils.getSession();
TeacherMapper mapper = session.getMapper(TeacherMapper.class);
Teacher teacher = mapper.getTeacher(2);
System.out.println(teacher);
session.close();
}
}