3. 使用Mybatis完成CRUD

捞月亮的小北發表於2024-06-11

前置工作準備

  • 建立Maven專案 , 引入依賴(mybatis依賴 ,mysql 驅動依賴 ,junit依賴 ,logback 依賴)
  • 將xml檔案放到類的根路徑下
  • 提供com.north.mybatis.utils.SqlSessionUtil工具類
  • 建立測試用例:com.north.mybatis.CarMapperTest


補充知識:什麼是CRUD
C: Create增
R: Retrieve查(檢索)
U: Update改
D: Delete刪

1. insert(Create

先說理論知識 : 在sql語句中使用 #{map集合的key}來完成傳值 等同於JDBC中的 ? ,#{}就是佔位符

<insert id="insertCar">
        insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
        values(null,'1003','豐田霸道',30.0,'2000-10-11','燃油車');
    </insert>

上述程式碼的問題是:

  • 值 顯然是寫死到配置檔案中的。
  • 這個在實際開發中是不存在的。一定是前端的form表單提交過來資料。然後將值傳給sql語句。

例如:JDBC的程式碼是怎麼寫的?String sql = "insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,?,?,?,?,?)";

在JDBC當中佔位符采用的是?,在mybatis當中是什麼呢?
和?等效的寫法是:#{}
在mybatis當中不能使用?佔位符,必須使用 #{} 來代替JDBC當中的 ?

{} 和 JDBC當中的 ? 是等效的。


insert的細節之處
java程式中使用POJO類給SQL語句的佔位符傳值:

  • 注意:佔位符#{},大括號裡面寫:pojo類的屬性名 , 但是這樣說也並不是很嚴謹

嚴格意義上來說:如果使用POJO物件傳遞值的話,#{}這個大括號中到底寫什麼?

  • 寫的是get方法的方法名去掉get,然後將剩下的單詞首字母小寫,然後放進去。
  • 例如:getUsername() --> #

也就是說mybatis在底層給 ? 傳值的時候,先要獲取值,怎麼獲取的 ?

  • 呼叫了pojo物件的get方法。例如:car.getCarNum(),car.getCarType(),car.getBrand()

如果採用map集合傳參,#{} 裡寫的是map集合的key,如果key不存在不會報錯,資料庫表中會插入NULL。
程式碼演示 ,這裡我自己吸取之前的教訓 ,把基本完整的給寫出來 ,防止以後再來看的話 , 不知道都代表著是什麼意思😊😊😊
工具類程式碼:

public class SqlSessionUtil {

    // 工具類的構造方法一般都是私有化的。
    // 工具類中所有的方法都是靜態的,直接採用類名即可呼叫。不需要new物件。
    // 為了防止new物件,構造方法私有化。
    private SqlSessionUtil(){}

    private static SqlSessionFactory sqlSessionFactory;

    // 類載入時執行
    // SqlSessionUtil工具類在進行第一次載入的時候,解析mybatis-config.xml檔案。建立SqlSessionFactory物件。
    static {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /*public static SqlSession openSession(){
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // SqlSessionFactory物件:一個SqlSessionFactory對應一個environment,一個environment通常是一個資料庫。
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }*/

    /**
     * 獲取會話物件。
     * @return 會話物件
     */
    public static SqlSession openSession(){
        return sqlSessionFactory.openSession();
    }
}

測試類:

@Test
    public void testInsertCarByPOJO() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        // 封裝資料
        Car car = new Car(null , "1005" , "比亞迪漢" , 30.0 , "2020-11-11" , "新能源");
        int rows = sqlSession.insert("insertCar" ,  car);
        System.out.println("插入成功的行數:" + rows);
        sqlSession.commit();
        sqlSession.close();
    }

CarMapper.xml檔案中的insert標籤:

<insert id="insertCar">
        insert into t_car(id , car_num , brand , guide_price , produce_time , car_type)
        values (null , #{carNum} , #{brand} , #{guidePrice} , #{produceTime} , #{carType})
    </insert>

2. delete (Delete)

注意:如果佔位符只有一個,那麼#{}的大括號裡可以隨意。但是最好見名知意。
需求:根據id進行刪除資料
CarMapper.xml檔案中的delete標籤:

<delete id="deleteCar">
        delete from t_car where id = #{id}
    </delete>

測試類:

@Test
    public void testDeleteById() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        int rows = sqlSession.delete("deleteCar", 16);
        System.out.println("刪除的行數:" + rows);
        sqlSession.commit();
        sqlSession.close();
    }

3. update(Update)

根據id修改某條資料的程式碼演示
CarMapper.xml檔案中的update標籤:

<update id="updateCar">
        update t_car
        set
            car_num = #{carNum} ,
            brand = #{brand} ,
            guide_price = #{guidePrice} ,
            produce_time = #{produceTime} ,
            car_type = #{carType}
        where
            id = #{id}
    </update>

測試類:

@Test
    public void testUpdateById() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        Car car = new Car(4L , "3333" , "梅特賽斯" , 146.8 , "2018-11-11" , "燃油車");
        int rows = sqlSession.update("updateCar", car);
        System.out.println("受影響的行數:" + rows);
        sqlSession.commit();
        sqlSession.close();
    }

4. select(Retrieve)

select語句和其它語句不同的是:查詢會有一個結果集

4.1 查詢一條資料

其中 ,查一個,根據主鍵查詢的話,返回的結果一定是一個。
需求:根據id進行查詢
需要特別注意的是:
select標籤中resultType屬性,這個屬性用來告訴mybatis,查詢結果集封裝成什麼型別的java物件。你需要告訴mybatis。
resultType通常寫的是:全限定類名。
注意:select語句查詢的時候,查詢結果集的列名是可以使用as關鍵字起別名的。
查詢的時候需要在select標籤中進行封裝結果接對映 ,也就是寫上resultType屬性 , 不然會進行報錯

CarMapper.xml檔案中的select標籤:

<select id="selectById" resultType="com.north.mybatis.pojo.Car">
        select
            id ,
            car_num as carNum ,
            brand ,
            guide_price as guidePrice ,
            produce_time as produceTime ,
            car_type as carType
        from
            t_car
        where
            id = #{id}
    </select>

測試類:

@Test
    public void testSelectById() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        Object selectOne = sqlSession.selectOne("selectById", 1);
        System.out.println(selectOne);
        sqlSession.close();
    }

查詢結果展示:

4.2 查詢多條資料

需求:查詢所有資料
需要注意的是:
resultType還是指定要封裝的結果集的型別。不是指定List型別,是指定List集合中元素的型別。
selectList方法:mybatis透過這個方法就可以得知你需要一個List集合。它會自動給你返回一個List集合。
CarMapper.xml檔案中的select標籤:

<select id="selectAll" resultType="com.north.mybatis.pojo.Car">
        select
            id ,
            car_num as carNum ,
            brand ,
            guide_price as guidePrice ,
            produce_time as produceTime ,
            car_type as carType
        from
            t_car
    </select>

測試類:

@Test
    public void testSelectAll() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        List<Object> selectAll = sqlSession.selectList("selectAll");
        selectAll.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

執行結果展示:

5. 關於SQL Mapper的namespace

namespace的作用
在sql mapper.xml檔案當中有一個namespace,這個屬性是用來指定名稱空間的。用來防止id重複。
實際上,本質上,mybatis中的sqlId的完整寫法:namespace.id

相關文章