公司近期新的小專案要移植到JBoss
,意味者強迫升級JDK
啦!
身為專案成員之一,順手pull
專案下來,開分支自己研究一下已經訂好的架構,嘗試加上新的endpoint
玩玩看。很好奇如果沒有那些複雜的抽象,最小可運作的程式會是長什麼樣子,再回來體會一下什麼叫過度設計(誤)。
本篇不會附上過多實際的程式碼,取而代之是試誤過程中遇到的問題,實際檢視log
並且排除問題後,再回來跟copilot
的覆盤記錄。
下列是詢問結果:
MyBatis 是一個持久化框架,用於簡化 Java 應用程序與資料庫之間的交互。它的主要功能包括:
恩,不懂的人光是第一句話就陣亡了,對吧?
不妨試者想想,在沒有這些持久化框架persistence framework
的情況下,要怎麼透過java
程式跟資料庫
溝通,進行資料操作?
諸如此類純手動需要花費很大心力的作業,可以都透過框架幫助處理。
src/
|-- main/
| |-- java/
| |-- com/
| |-- example/
| |-- demo/
| |-- DemoApplication.java
| |-- controller/
| |-- StudentController.java
| |-- mapper/
| |-- StudentMapper.java
| |-- model/
| |-- Student.java
| |-- service/
| |-- StudentService.java
|-- main/resources/
| |-- application.properties
| |-- mapper/
| |-- StudentMapper.xml
請copilot
提供給我一個最簡單的RESTful API
,只要get request拿
取學生資料表全部資訊回傳json
格式,架構示例如上。
運作過程簡述會是:
url endpoint
url endpoint
對應到controller
內特定的方法進行處理service
進行處理service
透過Mapper
對資料庫操作,拿回指定資料,轉換成model
再回傳Mybatis
負責的部分是提供了Mapper Interface
,其中簡單的小專案可以採用把SQL
寫在Annotation
中,複雜語法或大型專案,則可以選擇另外定義XML
檔案。
下面問著問著就變成USER
了,不過不影響觀念上的本質。
@Mapper
public interface UserMapper {
@Select("SELECT id, name, email FROM users WHERE id = #{id}")
User selectUser(int id);
}
也可以把SQL
另外定義成常數,再放入annotation
@Mapper
public interface UserMapper {
User selectUser(@Param("id") int 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.example.UserMapper">
<select id="selectUser" resultType="com.example.User">
SELECT id, name, email
FROM users
WHERE id = #{id}
</select>
</mapper>
官方文件似乎是建議使用XML,可以做較多變化跟處理,我自己則有幾個開發上不太喜歡的地方:
問題是發生在執行SQL後,拿到資料要轉換成對應的model
發生的狀況。網路上只找到幾個可能的狀況:
resultMap
中,轉換的property
有空格setter
一開始我是採用record
進行實作,使用Annotation
正常運作,但透過XML
才發生問題,問了得到下列答覆:
這個問題確實很有趣!在使用 @Select
註解時,與 XML 配置相比,有一些差異可能影響 record
類的行為。
@Select
註解時,MyBatis 會更加依賴構造函數參數而不是 setter
方法來實例化對象。因為 record
類本身就是不可變的,MyBatis 可以自動識別構造函數並使用它來創建對象。這與 XML 配置時依賴 setter
方法的行為有所不同。意思是record
是immutable
的設計,所以本來就沒有提供setter,
而XML
配置的mapper
是認setter
來進行轉換處理,跟Annotation
不一樣,是透過constructor
進行轉換。
沒辦法,為了制度及一些相容性問題,只好改回去使用Lombok
的@Data
。