MyBatis的CURD操作(Mapper動態代理)

在前面例子中 (Dao接口實現類) 自定義 Dao 接口實現類時發現一個問題: Dao 的實現類其實並沒有幹什麼實質性的工作,它僅僅就是通過 SqlSession 的相關 API 定位到映射文件 mapper 中相應 id 的 SQL 語句,真正對 DB 進行操作的工作其實是由框架通過 mapper 中的 SQL 完成的。

所以, MyBatis 框架就拋開了 Dao 的實現類,直接定位到映射文件 mapper 中的相應 SQL語句,對 DB 進行操作。這種對 Dao 的實現方式稱爲 Mapper 的動態代理方式。Mapper 動態代理方式無需程序員實現 Dao 接口。接口是由 MyBatis 結合映射文件自動生成的動態代理實現的。

映射文件的 namespace 屬性值

一般情況下,一個 Dao 接口的實現類方法使用的是同一個 SQL 映射文件中的 SQL 映射 id。 所以, MyBatis 框架要求,將映射文件中 <mapper/> 標籤的 namespace 屬性設爲 Dao 接口的全類名,則系統會根據方法所屬 Dao 接口,自動到相應 namespace 的映射文件中查找相關的 SQL 映射。

簡單來說,通過接口名即可定位到映射文件 mapper。

<mapper namespace="com.huang.dao.IStudentDao">

修改日誌輸出控制文件

mapper 的 namespace 修改了,則需要將日誌輸出控制文件中 logger 的輸出對象進行修改。

##define a logger
log4j.logger.com.huang.dao.IStudentDao=trace,console

Dao 接口方法名

MyBatis 框架要求, 接口中的方法名,與映射文件中相應的 SQL 標籤的 id 值相同。 系統會自動根據方法名到相應的映射文件中查找同名的 SQL 映射 id。簡單來說,通過方法名就可定位到映射文件 mapper 中相應的 SQL 語句。

public interface IStudentDao {
	void insertStudent(Student student);
	
	void deleteStudentById(int id);
	void updateStudent(Student student);
	
	List<Student> selectAllStudents();
	
	Student selectStudentById(int id);
	List<Student> selectStudentsByName(String name);
}

刪除 Dao 實現類

由於通過調用 Dao 接口的方法,不僅可以從 SQL 映射文件中找到所要執行 SQL 語句,還可通過方法參數及返回值,將 SQL 語句的動態參數傳入,將查詢結果返回。所以, Dao 的實現工作,完全可以由 MyBatis 系統自動根據映射文件完成。

修改測試類

public class MyTest {
	private IStudentDao dao;
	private SqlSession session;

	@Before
	public void setUp() {
		session = MyBatisUtils.getSqlSession();
		dao = session.getMapper(IStudentDao.class);
	}
	
	@After
	public void tearDown() {
		if (session != null) {
			session.close();
			
		}
	}
	
	@Test
	public void test01() {
		Student student = new Student("張三", 23, 93.5);
		System.out.println("插入前:student = " + student);
		dao.insertStudent(student);
		System.out.println("插入後:student = " + student);
		//添加SqlSession的提交方法
		session.commit();
	}
	
	/*@Test
	public void test02() {
		Student student = new Student("張三", 23, 93.5);
		System.out.println("插入前:student = " + student);
		dao.insertStudentCacheId(student);
		System.out.println("插入後:student = " + student);
	}*/
	
	@Test
	public void test03() {
		dao.deleteStudentById(22);
		//添加SqlSession的提交方法
		session.commit();
	}
	
	@Test
	public void test04() {
		Student student = new Student("張大三", 23, 93.5);
		student.setId(8);
		dao.updateStudent(student);
		//添加SqlSession的提交方法
		session.commit();
	}

多查詢條件無法整體接收問題的解決

在實際工作中,表單中所給出的查詢條件有時是無法將其封裝爲一個對象的,也就是說,查詢方法只能攜帶多個參數,而不能攜帶將這多個參數進行封裝的一個對象。對於這個問題,有兩種解決方案。

1. 將這多個參數封裝爲一個 Map

(1)修改 Dao 接口

public interface IStudentDao {
	List<Student> selectStudentsByCondition(Map<String, Object> map);
}

(2)修改映射文件

<select id="selectStudentsByCondition" resultType="Student">
		select id,name,age,score 
		from student 
		where name like '%' #{nameCon} '%' 
		and age > #{ageCon}
		and score > #{scoreCon}
	</select>

(3)修改測試類

	//根據 map 查詢
	@Test
	public void test01() {
		Student stu = new Student("王小五", 20, 96.5);
		
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("nameCon", "王");
		map.put("ageCon", 23);
		map.put("stu", stu);
		
		List<Student> students = dao.selectStudentsByCondition(map);
		
		for (Student student : students) {
			System.out.println(student);
			
		}
	}

2. 多個參數逐個接收

對於 mapper 中的 SQL 語句,可以通過參數索引 #{index} 的方式逐個接收每個參數。

(1)修改 Dao 接口

public interface IStudentDao {
	List<Student> selectStudentsByCondition(String name, int age);
}

(2)修改映射文件

<select id="selectStudentsByCondition" resultType="Student">
		select id,name,age,score 
		from student 
		where name like '%' #{0} '%' 
		and age > #{1}
	</select>

(3)修改測試類

	@Test
	public void test01() {
		
		List<Student> students = dao.selectStudentsByCondition("張", 23);
		for (Student student : students) {
			System.out.println(student);
		}
	}

問題:
#{} 中可以放什麼內容?
1)參數對象的屬性;
2)隨意內容,此時的 #{} 是個佔位符;
3)參數爲 map 時的 key;
4)參數爲 map 時,若 key 所對應的 value 爲對象,則可將該對象的屬性放入;
5)參數的索引號。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章