大家好,我是 @老K玩代碼。
本期是關于MyBatis基礎教程講義的最後一講了,我們要來說說MyBatis的一個特性——注解。
MyBatis裡有很多功能注解,我們可以通過這些注解,實作各種映射器接口,替代mapper.xml類檔案的作用。
到底應該怎麼做呢?我們一起開看一下。
之前的内容可以通過下面的連結檢視:
- 老K玩代碼:MyBatis精講(一)MyBatis基礎配置及持久層連接配接建立代碼實戰
- 老K玩代碼:MyBatis精講(二)常用工具MyBatisUtils類的實作
- 老K玩代碼:MyBatis精講(三)一篇文章讓你學會如何用MyBatis擷取資料
- 老K玩代碼:MyBatis精講(四)查詢資料方法精講及實戰代碼集合
- 老K玩代碼:MyBatis精講(五)CRUD操作及實戰代碼精講
- 老K玩代碼:MyBatis精講(六)一對多資料查詢實戰分享
- 老K玩代碼:MyBatis精講(七)動态SQL查詢方法實戰代碼講解
這一講對的内容有點多,建議可以先收藏起來,慢慢讀,慢慢消化。
一、準備工作
通過maven建立項目,以及在pom檔案裡配置依賴庫相關的步驟就不介紹了,有需要的可以看《MyBatis精講(一)MyBatis基礎配置及持久層連接配接建立代碼實戰》。
項目配置好後,我們先把資料庫通過sql語句的方式導入到項目裡:
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`depart` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`salary` decimal(10, 2) NOT NULL,
`age` int NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
`did` int UNSIGNED NOT NULL AUTO_INCREMENT,
`depart` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`member` int NULL DEFAULT NULL,
PRIMARY KEY (`did`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
INSERT INTO `employee` VALUES (5001, '趙乾', '銷售部', 6000.00, 28);
INSERT INTO `employee` VALUES (5002, '孫禮', '銷售部', 7000.00, 34);
INSERT INTO `employee` VALUES (6001, '周武', '技術部', 6500.00, 27);
INSERT INTO `employee` VALUES (6002, '鄭望', '技術部', 7500.00, 40);
INSERT INTO `department` VALUES (1, '銷售部', 5);
INSERT INTO `department` VALUES (2, '技術部', 6);
在項目路徑下建立一個dao目錄(本例中的完整路徑為./src/main/java/koder/mybatis/dao)。
DAO是Data Annotation Objects的首字母,表示資料注解對象實體。
然後在mybatis-config.xml進行如下配置(注:mybatis-config.xml檔案路徑參考《MyBatis精講(一)MyBatis基礎配置及持久層連接配接建立代碼實戰》中的内容。)
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="True"/>
</settings>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/javasql?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="koder.mybatis.dao"/>
</mappers>
</configuration>
- <package>是用來配置映射器包的标簽,一般是包含映射器接口的目錄位置。
二、查詢資料
我們首先在映射器包(本例中該路徑為./src/main/java/koder/mybatis/dao)下建立一個接口類——HRDao.java,并編寫以下内容:
- HRDao.java
import koder.mybatis.dto.EmployeeDTO;
import koder.mybatis.entity.Employee;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface HRDao {
@Select("select * from employee where id = #{value}")
public Employee selectById(@Param("value") Integer id);
}
- koder.mybatis.dto.EmployeeDTO是後面案例會用到的資料傳輸對象類,在這裡先導入;
- org.apache.ibatis.annotations是mybatis的注解類;
- 用@Select注解,定義sql查詢語句;
- 對于sql查詢語句中的可變參數,用#{value}表示,這裡的value是自定義的,可以是任何變量名稱;
- 用@Param注解定義變量參數,便是該參數對應在sql查詢語句中的名稱,本例中表示java方法參數id就是sql語句中的value值。
這樣,一個資料注解對象、也就是注解映射器就寫好了,接下來我們編寫測試用例:
- MyBatisTest.java(檔案路徑和基本配置參見《MyBatis精講(三)一篇文章讓你學會如何用MyBatis擷取資料》)
@Test
public void TestDaoSelectById() {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
HRDao hrDao = sqlSession.getMapper(HRDao.class);
Employee emp = hrDao.selectById(6001);
System.out.println(emp.getName());
}catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
- 通過SqlSession的getMapper方法擷取資料注解對象類,本例中為HRDao的class;
- 調用HRDao的查詢方法,就能直接對應映射的sql語句,執行查詢,傳回對應資料類型;
上述代碼運作後的結果為:
周武
三、插入資料
插入資料的映射接口,可以用@Insert注解器實作:
- HRDao.java
@Insert("insert into employee(name, depart, salary, age) values (#{name}, #{depart}, #{salary}, #{age})")
@SelectKey(statement = "select last_insert_id()", keyProperty = "id", keyColumn = "id", before = false, resultType = Integer.class)
public int insert(Employee employee);
- 上述代碼内容,應寫在HRDao接口内,是HRDao的内部方法;
- @Insert可以接收sql的插入語句,如果傳入的是實體對象(如Employee),@Insert注解器會自動将實體類的成員變量通過駝峰轉換傳入sql語句;
- @SelectKey相當于MyBatis的xml文法中的<selectKey>功能一緻,定義的sql語句會和主語句一起被執行。statement參數接收sql語句,keyProperty接受java類中的成員變量名,keyColumn接受資料庫中的字段列名,before表示該語句是在主語句之前還是之後執行,resultType是将執行後得到的資料存入那個資料類型中;
然後在MyBatisTest.java中寫入測試用例:
- MyBatisTest.java
@Test
public void TestDaoInsert() {
SqlSession session = null;
try {
session = MyBatisUtils.openSession();
Employee employee = new Employee();
employee.setAge(34);
employee.setDepart("技術部");
employee.setName("儲緯");
employee.setSalary(7700.0f);
HRDao hrDao = session.getMapper(HRDao.class);
hrDao.insert(employee);
session.commit();
System.out.println(employee.getId());
} catch (Exception e) {
if (session != null) {
session.rollback();
}
throw new RuntimeException(e);
} finally {
MyBatisUtils.closeSession(session);
}
}
- 由于映射器接口中insert方法傳入的參數是Employee,是以我們先執行個體化一個Employee執行個體,傳入到HRDao.insert方法中;
- insert方法使用事務機制,是以完成方法調用後,需要commit才能生效,并且失敗後需要rollback。
執行上述代碼後,得到結果如下:
6003
并且,檢視資料庫也能發現新的資料被錄入成功!
四、修改資料
編寫映射接口。
- HRDao.java
@Update("update employee set name = #{name}, depart = #{depart}, salary = #{salary}, age = #{age} where id = #{id}")
public int update(Employee employee);
- @Update是更新資料的注解方法,文法特征與@Insert類似。
而測試用例編寫如下:
- MyBatis.java
@Test
public void TestDaoUpdate() {
SqlSession session = null;
try {
session = MyBatisUtils.openSession();
HRDao hrDao = session.getMapper(HRDao.class);
Employee employee = hrDao.selectById(6001);
employee.setSalary(7900f);
hrDao.update(employee);
session.commit();
System.out.println(employee.getId());
} catch (Exception e) {
if (session != null) {
session.rollback();
}
throw new RuntimeException(e);
} finally {
MyBatisUtils.closeSession(session);
}
}
- 由于修改資料,需要先從資料庫中擷取,我們用查詢方法select ById擷取Employee執行個體;
- 調用HRDao的update方法,執行更新資料的操作;
- 由于是事務機制,是以需要添加commit和rollback語句;
執行上述代碼後,可以發現資料庫中對應條目的薪酬已改為7900.00。
五、删除資料
編寫映射接口:
- HRDao.java
@Delete("delete from employee where id = #{value}")
public int delete(@Param("value") Integer id);
- @Delete是删除資料的注解類,注意要點與@Update、@Insert一緻;
- 參數用@Param進行映射比對;
測試用例編寫如下:
- MyBatis.java
@Test
public void TestDaoDelete() {
SqlSession session = null;
try {
session = MyBatisUtils.openSession();
HRDao hrDao = session.getMapper(HRDao.class);
hrDao.delete(6003);
session.commit();
} catch (Exception e) {
if (session != null) {
session.rollback();
}
throw new RuntimeException(e);
} finally {
MyBatisUtils.closeSession(session);
}
}
執行上述代碼後,可以發現,之前插入的資料“儲緯”已被删除;
六、自定義ResultMap連結清單查詢
之前講過通過mapper.xml文法連表查詢需要用到resultMap标簽,那麼,如果用資料注解對象,如何解決連結清單查詢的問題呢?
首先在HRDao.java編寫接口:
- HRDao.java
@Select("select e.*, d.* from employee e, department d where e.depart = d.depart")
@Results({
@Result(property="employee.id", column="id", id = true),
@Result(property="employee.name", column="name"),
@Result(property="employee.salary", column="salary"),
@Result(property="employee.depart", column="depart"),
@Result(property="employee.depart", column="depart"),
@Result(property="employee.age", column="age"),
@Result(property="department.did", column="did"),
@Result(property="department.member", column="member")
})
public List<EmployeeDTO> selectDTO();
- 我們先用@Select編寫連結清單查詢的語句;
- 利用@Results注解定義目前方法的結果類;
- 在@Results中通過@Result對資料屬性進行映射,參數property接收java類中的成員變量,參數column接收資料庫中的字段列名,id表示該字段是否作為id索引;
測試用例:
- MyBatis.java
@Test
public void TestDaoSelectDto() {
SqlSession session = null;
try {
session = MyBatisUtils.openSession();
HRDao hrDao = session.getMapper(HRDao.class);
List<EmployeeDTO> emps = hrDao.selectDTO();
for (EmployeeDTO emp: emps) {
System.out.println(emp.getEmployee().getName() + "所在的部門有"+emp.getDepartment().getMember() + "人。");
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
MyBatisUtils.closeSession(session);
}
}
- DTO連結清單查詢和普通查詢代碼邏輯一樣;
執行上述代碼,獲得如下結果:
趙乾所在的部門有5人。
孫禮所在的部門有5人。
周武所在的部門有6人。
鄭望所在的部門有6人。
以上,就是MyBatis的資料注解對象DAO常見的使用方法。
DAO相比起xml映射器,代碼的可讀性更強,對java工程師更友好,而且java編譯器能提供文法支援,更便于工程師們排查錯誤。
熟練掌握DAO映射接口的寫法,對高效使用MyBatis有很大的幫助!
感謝你看到這裡。
如果你對老K分享的内容有任何疑問,歡迎随時在評論區留言或者私信我。
正在學習的小夥伴記得給老K一個贊哦,你的支援是我持續輸出課程内容最大的動力。
結束語
我是專注于開發領域的@老K玩代碼,會持續生産關于如何學習程式設計語言的優質内容。
如果你對程式設計和項目開發有興趣,可以關注我。
#頭條創作挑戰賽#