一個系列搞定MyBatis:MyBatis快速上手增刪改查

Hi丶ImViper發表於2020-10-21

MyBatis快速上手增刪改查

引言-絮絮叨叨

作為一個快樂的小碼農,在每一個階段往往都在重複寫著不同版本的,學生管理,使用者管理,註冊登入,從 JavaSE 的控制檯版,或者 GUI 版,再到 JavaWeb的 JSP版,再到純粹使用 HTML 作為前端展示的版本,以及使用一個更新的技術,在此其中,我們用過 txt 做資料庫,用 XML 也可以,到現在常用的 MySQL,增刪改查一直是我們必不可少的一部分內容,即使你不懂原理,即使你對這個技術的理解不是很深刻,拿出你的增刪改查,噼裡啪啦就是一段亂敲,好歹還是能讓你著手先做起來(當然,對技術的理解還是很重要的),今天就和大家聊一聊 MyBatis 這門技術的 CURD (增刪改查)

優化測試方法

在測試方法中,讀取配置檔案,生產 SqlSession,釋放資源等等,在每一測試方法的時候,都是重複的,所以我們完全可以提出出這一部分,防止大量的重複程式碼

@Before
    public  void init() throws Exception{
        //讀取配置檔案
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //建立SqlSessionFactory工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

        //使用工廠生產SqlSession物件
        sqlSession= factory.openSession();
        //使用SqlSession建立Mapper介面的代理物件
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

 @After
    public void destroy() throws Exception{
        sqlSession.close();
        inputStream.close();
    }

在這兩個方法上增加 @Before 和 @Aftrer 註解,就可以保證,init() 和 destory() 這兩個方法,分別在我們真正被測試的方法的前後執行

(一) 增添操作

(1) 編寫程式碼

首先,在 UserMapper 介面中 增加對應的方法

public interface UserMapper {
    /**
     * 增加使用者
     * @param user
     */
    void addUser(User user);
}

接著,在SQL對映檔案中,增加新增的對映配置,這些有關內容放在 <insert></insert>標籤對中,具體程式碼如下

<insert id="addUser" parameterType="cn.ideal.domain.User">
	insert into user(username,telephone,birthday,gender,address)values(#{username},#{telephone},#{birthday},#{gender},#{address})
</insert>

(2) 說明:

1、id 屬性,自然是對應的方法名,而由於這裡,我們並不需要拿到返回資訊,所以這裡並沒有返回引數 resultType,而方法中的引數又為一個 JavaBean 類,也就是User實體類,所以需要在標籤屬性中,新增一個 parameterType 屬性,其中需要指定這個實體類

2、在文字中書寫插入的SQL語句,由於實體類中已經快捷生成了對應的 get set 方法,所一可以使用 #{}的方式代表對應的值

3、提示,資料庫中id為自增,所以並不需要設定 id

(3) 注意:

由於新增是更新類的語句,所以在執行插入語句後,需要提交事務,也就是執行對應的 commit方法,以提交更新操作,若沒有這一句,即使不會報錯,也無法正常存入,會被回滾,且這個id被佔用

(4) 測試程式碼:

/**
     * 測試新增使用者
     * @throws Exception
     */
    @Test
    public void testUpdateUser() throws Exception{
        User user = new User();
        user.setId(17);
        user.setUsername("修改");
        user.setTelephone("18899999999");
        user.setBirthday(new Date());
        user.setGender("女");
        user.setAddress("廣州");

        //執行方法
        userMapper.updateUser(user);

    }

(5) 執行結果:

控制檯:

img

(6) 獲取新增使用者的id值

首先對於 MySQL自增主鍵來說,在執行 insert語句之前,MySQL 會自動生成一個自增主鍵,insert執行後,通過 SELECT 1603013 可以獲取這條剛插入記錄的自增主鍵

在 SQL 對映配置檔案中,需要藉助 <selectKey></selectKey> 標籤,有一個屬性比較特殊,order 屬性,它代表著相對於插入操作的執行時間,before-之前,after-之後

注:該標籤插入到 <select></select>

<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
	SELECT 1603013;
</selectKey>

測試一下

@Test
public void testAddUser() throws Exception{
    User user = new User();
    user.setUsername("增加");
    user.setTelephone("12266660000");
    user.setBirthday(new Date());
    user.setGender("男");
    user.setAddress("珠海");
    System.out.println("執行插入前" + user);
    //執行方法
    userMapper.addUser(user);
    System.out.println("執行插入後" + user);
}

執行效果

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-MPjQcw14-1603254452475)(https://user-gold-cdn.xitu.io/2020/2/5/1701312949c67daa?imageView2/0/w/1280/h/960/format/webp/ignore-error/1)]

img

(二) 修改操作

(1) 編寫程式碼

在 UserMapper 介面中增加修改方法

public interface UserMapper {
    /**
     * 更新使用者
     * @param user
     */
    void updateUser(User user);
}

在 SQL 對映檔案中增加語句,內容包括在 <update></update> 中,需要注意的基本與新增操作是一致的

<update id="updateUser" parameterType="cn.ideal.domain.User">
	update user set username=#{username},telephone=#{telephone},birthday=#{birthday},gender=#{gender},address=#{address} where id=#{id}
</update>

(2) 測試程式碼

/**
     * 測試新增使用者
     * @throws Exception
     */
    @Test
    public void testAddUser() throws Exception{
        User user = new User();
        user.setUsername("增加");
        user.setTelephone("12266668888");
        user.setBirthday(new Date());
        user.setGender("女");
        user.setAddress("成都");

        //執行方法
        userMapper.addUser(user);

    }

(3) 執行效果

img

img

(三) 刪除操作

(1) 編寫程式碼

介面中增加刪除方法

public interface UserMapper {
    /**
     * 刪除使用者
     * @param uid
     */
    void deleteUser(Integer uid);
}

在SQL對映檔案中,使用 <delete></delete> 標籤對進行內容的書寫,需要注意的是,由於我們傳入的引數是一個 Integer型別的使用者id,所以引數型別的值為 parameterType

<delete id="deleteUser" parameterType="java.lang.Integer">
	delete from user where id=#{id}
</delete>

(2) 測試程式碼

/**
 * 測試刪除使用者
 * @throws Exception
 */
@Test
public void testDeleteUser() throws Exception{
    //執行方法
    userMapper.deleteUser(17);
}

(3) 執行效果

img

img

(四) 模糊查詢

由於查詢全部非常簡單,這裡就不展示了,基本流程都是一樣的

(1) 編寫程式碼

在 UserMapper 介面中編寫方法

public interface UserMapper {
    /**
     * 通過姓名模糊查詢
     * @param username
     * @return
     */
    List<User> findByName(String username);
}

在 SQL 對映檔案中新增查詢語句

<select id="findByName" parameterType="java.lang.String" resultType="cn.ideal.domain.User">
	select * from user where username like #{username}
</select>

(2) 測試程式碼

/**
 * 測試模糊查詢
 * @throws Exception
 */
@Test
public void testFindByName() throws Exception{
	List<User> users = userMapper.findByName("%張%");
	for (User user : users){
    	System.out.println(user);
    }
}

(3) 注意

在使用模糊查詢的時候,我們需要在查詢條件的兩側拼接兩個 “%” 字串,這個時候有兩種解決方案,一種就是像在我上述程式碼中,在測試時將字串補充完整,還有一種方式就是 使用 ${} ,它在 SQL配置檔案中代表一個 “拼接符號” ,也就是說可以這樣寫 SQL語句

select * from user where username like '%{value}'

可接受的型別有,普通型別(此情況下{}內部只能寫value),JavaBean,HashMap

但是使用%{} 拼接字串的時候,會引起 SQL隱碼攻擊,所以不是很推薦使用

(4) 執行效果

img

(五) 自定義包裝類作為查詢條件

Mapper 的輸入對映樣例中,我們對於基本資料型別和基本資料包裝類,都有了一定的瞭解,而下面我們來聊一聊關於相對複雜的一種情況,那就是自定義包裝類

先講一個需求:還是關於使用者的查詢,但是查詢條件複雜了一些,不僅僅侷限於使用者的資訊,而且可能還包括訂單,購物車,或者與使用者一些行為相關的資訊,那麼如何實現這樣一種需求呢?

那我們想,可不可以,在 User 類中增加一些我們需要的資訊

  • 從程式碼的角度來看,在 User 中新增的欄位與資料庫不一定能對應起來,在原來的基礎上做修改,就會影響 User 作為資料庫對映物件的功能,所以我們可以建立一個 UserInstance 類,繼承 User類就可以在其中為某些業務新增一些不屬於資料庫的欄位了

(1) 定義包裝類

package cn.ideal.domain;

public class QueryUserVo {
    private UserInstance userInstance;

    public UserInstance getUserInstance() {
        return userInstance;
    }

    public void setUserInstance(UserInstance userInstance) {
        this.userInstance = userInstance;
    }

    //其他查詢條件,例如訂單,購物車等等
}

(2) 配置 Mapper 檔案

我們這裡使用使用者的性別以及對姓名的模糊查詢,來寫SQL 當然,你也可以自己通過別的資訊寫SQL

<select id="findUserByVo" parameterType="cn.ideal.domain.QueryUserVo" resultType="cn.ideal.domain.UserInstance">
	select * from user where user.gender=#{userInstance.gender} and user.username like #{userInstance.username}
</select>

在QueryUserVo 中,封裝的是查詢資訊的各種物件,為什麼上述程式碼可以直接通過 userInstance.gender 直接取出對應的屬性,這種方式叫做 OGNL 表示式,在類中 我們的寫法通常是 user.getUsername 但在寫法上,OGNL 表示式將get給省略了

(3) 測試程式碼

/**
 * 包裝物件作為查詢引數
 * @throws Exception
 */
@Test
public void testFindUserByVo() throws Exception{
	//建立包裝物件,設定查詢條件
    QueryUserVo queryUserVo = new QueryUserVo();
    UserInstance userInstance = new UserInstance();
    userInstance.setGender("女");
    userInstance.setUsername("%張%");
    queryUserVo.setUserInstance(userInstance);

    //呼叫 UserMapper 的方法
    List<UserInstance> userInstances 
      	= userMapper.findUserByVo(queryUserVo);
    for (UserInstance u : userInstances){
		System.out.println(u);
    }
}

(4) 執行效果

img

相關文章