mybatis的增刪改查

ivanlee717發表於2024-12-05

spring boot增刪改查

查部分欄位

這個原理都比較簡單,根據我前面的部落格定義好service和mapper元件就行。

但是這裡要強調一個用法@builder

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
### The error may exist in file [D:\store\target\classes\mapper\UserMapper.xml]
### The error may involve com.ivan.store.mapper.UserMapper.findAll
### The error occurred while handling results
### SQL: SELECT uid,username,password FROM t_user
### Cause: java.lang.IndexOutOfBoundsException: Index: 3, Size: 3

我在執行SELECT uid,username,password FROM t_user這個欄位的時候會報上面的錯誤,但是如果執行 SELECT * FROM t_user

就不會有問題。image-20241204105456745

@Data和@Builder一起用:我們發現沒有了預設的構造方法。如果手動新增無引數構造方法或者用@NoArgsConstructor註解都會報錯!

我們使用註解的方式,底層本質就是反射幫我們生成了一系列的setter、getter方法,但是今天發現@Builder註解會把物件的預設值清掉
Lombok 的 @Data 註解:

  • 自動新增了 getter、setter、toString、equals、hashCode 方法。
  • 如果沒有其他建構函式宣告,還會新增一個全引數建構函式(包含所有欄位)。

Lombok 的 @Builder 註解:

  • 自動生成構建器模式所需的方法和類。
  • 預設情況下,@Builder 不會自動新增無參建構函式。

自定義實體類中缺失了無參構造方法(同時使用@Data和@Builder也會造成無參構造方法缺失),MyBstais框架在處理查詢SQL的返回結果時,mybatis會呼叫無參構造方法來構造例項,然後使用setter方法設定成員變數值,因為沒有無參構造沒辦法將查詢出的欄位對映到自定義實體類的成員變數上,由此產生該異常;
所以解決辦法就是我們把註解都加上就行

image-20241204110115307

現在我們可以得到一個List<User>的列表image-20241204110442330

雖然這個表非常的簡單,但是在複雜的專案裡面可能會提取出很多個欄位,然後根據DTO規範返回特定的一些資料,那麼型別轉換就顯得非常關鍵,這裡我們使用一個叫ModelMapper的依賴。

ModelMapper

專案中物件與物件賦值轉換使用的頻率非常的高,比如資料庫表實體物件(Entity)與業務類物件(Model)之間的賦值傳遞,或者模型物件(Model)與檢視物件(ViewModel)之間的賦值傳遞。如果我們一個一個欄位的賦值,將是非常繁瑣並且毫無價值的重複工作,此時雖然我們可以自己透過反射提取個公共的方法來處理,但是更高效的方式是檢視是否有第三方已經提供了比較成熟穩定的工具包,避免重複造輪子的工作。
image-20241204141732338

首先弄好依賴,然後進行下面的操作

package com.ivan.store.service.impl;

import com.ivan.store.entity.dto.UserDto;
import com.ivan.store.entity.model.User;
import com.ivan.store.mapper.UserMapper;
import com.ivan.store.service.OperateService;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service//不新增這個會報錯
public class OperateServiceImpl implements OperateService
{
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ModelMapper modelMapper;


    public List<UserDto>  findAll(){
        List<User> users = userMapper.findAll();
        List<UserDto> userDtos = new ArrayList<>();
        for(User user: users){
            UserDto userDto = modelMapper.map(user,UserDto.class);
            userDtos.add(userDto);
        }
        return userDtos;
    }
}

將user物件列表全部對映為userDto的列表。這樣我們就可以將資料按照規定格式進行返回。

@GetMapping("/findAll")
public List<UserDto> findAll(){
    return operateService.findAll();
}

image-20241204142348055

刪除操作

學習一下post請求,把刪除的語句設定成了根據使用者名稱和密碼去匹配資訊來刪除。

<!-- 刪除使用者 -->
    <delete id="delUser" parameterType="com.ivan.store.entity.model.User" >
        DELETE FROM t_user WHERE username = #{username} AND password = #{password}
    </delete>

所以傳輸的物件是一個User物件,最後呼叫findAll來檢視結果。

image-20241204165734888

image-20241204165804263

image-20241204154139313

image-20241204160854032

把uid是7的這個使用者刪了

更新操作

只要記住,首先把xml檔案裡新增好對應的sql語句,欄位要和實體定義或者resultmap寫好的對應上,然後去service裡面完成這個方法的實現,最後在controller裡面完成路徑設定就可以了。

<update id="update" parameterType="com.ivan.store.entity.model.User">
    update t_user
    <set>
        username = #{username},
        password = #{password}
    </set>
    WHERE uid = #{uid}
</update>
public List<UserDto> update(User user){
        userMapper.update(user);
        return findAll();
    }
@PostMapping("/UPDATE")
public List<UserDto> UPDATE(User user){
    return operateService.update(user);
}

image-20241205082732549

插入操作

可見用一個專案把控制層、業務層、持久層說明白了,每一句話都講的很清楚 - ivanlee717 - 部落格園

相關文章