1. 程式人生 > >MyBatis學習總結(四)——解決欄位名與實體類屬性名不相同的衝突

MyBatis學習總結(四)——解決欄位名與實體類屬性名不相同的衝突

 在平時的開發中,我們表中的欄位名和表對應實體類的屬性名稱不一定都是完全相同的,下面來演示一下這種情況下的如何解決欄位名與實體類屬性名不相同的衝突。

一、準備演示需要使用的表和資料

CREATE TABLE orders(
    order_id INT PRIMARY KEY AUTO_INCREMENT,
    order_no VARCHAR(20), 
    order_price FLOAT
);
INSERT INTO orders(order_no, order_price) VALUES('aaaa', 23);
INSERT INTO orders(order_no, order_price) VALUES('bbbb', 33);
INSERT INTO orders(order_no, order_price) VALUES('cccc', 22);

二、定義實體類

package me.gacl.domain;

/**
 * @author gacl
 * 定義orders表對應的實體類
 */
public class Order {
    /**
     * 
    CREATE TABLE orders(
        order_id INT PRIMARY KEY AUTO_INCREMENT,
        order_no VARCHAR(20), 
        order_price FLOAT
    );
     */
    
    //Order實體類中屬性名和orders表中的欄位名是不一樣的
    private int id;                //id===>order_id
    private String orderNo;        //orderNo===>order_no
    private float price;        //price===>order_price

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Order [id=" + id + ", orderNo=" + orderNo + ", price=" + price+ "]";
    }
}

三、編寫測試程式碼

3.1、編寫SQL的xml對映檔案

  1、建立一個orderMapper.xml檔案,orderMapper.xml的內容如下:

<?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,namespace的值習慣上設定成包名+sql對映檔名,這樣就能夠保證namespace的值是唯一的
例如namespace="me.gacl.mapping.orderMapper"就是me.gacl.mapping(包名)+orderMapper(orderMapper.xml檔案去除字尾)
 -->
<mapper namespace="me.gacl.mapping.orderMapper">
    
    <!-- 
        根據id查詢得到一個order物件,使用這個查詢是查詢不到我們想要的結果的,
        這主要是因為實體類的屬性名和資料庫的欄位名對應不上的原因,因此無法查詢出對應的記錄
     -->
    <select id="getOrderById" parameterType="int" 
        resultType="me.gacl.domain.Order">
        select * from orders where order_id=#{id}
    </select>
    
    <!-- 
        根據id查詢得到一個order物件,使用這個查詢是可以正常查詢到我們想要的結果的,
        這是因為我們將查詢的欄位名都起一個和實體類屬性名相同的別名,這樣實體類的屬性名和查詢結果中的欄位名就可以一一對應上
     -->
    <select id="selectOrder" parameterType="int" 
        resultType="me.gacl.domain.Order">
        select order_id id, order_no orderNo,order_price price from orders where order_id=#{id}
    </select>
    
    <!-- 
    根據id查詢得到一個order物件,使用這個查詢是可以正常查詢到我們想要的結果的,
    這是因為我們通過<resultMap>對映實體類屬性名和表的欄位名一一對應關係 -->
    <select id="selectOrderResultMap" parameterType="int" resultMap="orderResultMap">
        select * from orders where order_id=#{id}
    </select>
    <!--通過<resultMap>對映實體類屬性名和表的欄位名對應關係 -->
    <resultMap type="me.gacl.domain.Order" id="orderResultMap">
        <!-- 用id屬性來對映主鍵欄位 -->
        <id property="id" column="order_id"/>
        <!-- 用result屬性來對映非主鍵欄位 -->
        <result property="orderNo" column="order_no"/>
        <result property="price" column="order_price"/>
    </resultMap>
    
</mapper>

 2、在conf.xml檔案中註冊orderMapper.xml對映檔案

<mappers>        
        <!-- 註冊orderMapper.xml檔案, 
        orderMapper.xml位於me.gacl.mapping這個包下,所以resource寫成me/gacl/mapping/orderMapper.xml-->
        <mapper resource="me/gacl/mapping/orderMapper.xml"/>
</mappers>

3.2、編寫單元測試程式碼

package me.gacl.test;

import me.gacl.domain.Order;
import me.gacl.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class Test2 {
    
    @Test
    public void testGetOrderById(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**
         * 對映sql的標識字串,
         * me.gacl.mapping.orderMapper是orderMapper.xml檔案中mapper標籤的namespace屬性的值,
         * getOrderById是select標籤的id屬性值,通過select標籤的id屬性值就可以找到要執行的SQL
         */
        String statement = "me.gacl.mapping.orderMapper.getOrderById";//對映sql的標識字串
        //執行查詢操作,將查詢結果自動封裝成Order物件返回
        Order order = sqlSession.selectOne(statement,1);//查詢orders表中id為1的記錄
        //使用SqlSession執行完SQL之後需要關閉SqlSession
        sqlSession.close();
        System.out.println(order);//列印結果:null,也就是沒有查詢出相應的記錄
    }
    
    @Test
    public void testGetOrderById2(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**
         * 對映sql的標識字串,
         * me.gacl.mapping.orderMapper是orderMapper.xml檔案中mapper標籤的namespace屬性的值,
         * selectOrder是select標籤的id屬性值,通過select標籤的id屬性值就可以找到要執行的SQL
         */
        String statement = "me.gacl.mapping.orderMapper.selectOrder";//對映sql的標識字串
        //執行查詢操作,將查詢結果自動封裝成Order物件返回
        Order order = sqlSession.selectOne(statement,1);//查詢orders表中id為1的記錄
        //使用SqlSession執行完SQL之後需要關閉SqlSession
        sqlSession.close();
        System.out.println(order);//列印結果:Order [id=1, orderNo=aaaa, price=23.0]
    }
    
    @Test
    public void testGetOrderById3(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**
         * 對映sql的標識字串,
         * me.gacl.mapping.orderMapper是orderMapper.xml檔案中mapper標籤的namespace屬性的值,
         * selectOrderResultMap是select標籤的id屬性值,通過select標籤的id屬性值就可以找到要執行的SQL
         */
        String statement = "me.gacl.mapping.orderMapper.selectOrderResultMap";//對映sql的標識字串
        //執行查詢操作,將查詢結果自動封裝成Order物件返回
        Order order = sqlSession.selectOne(statement,1);//查詢orders表中id為1的記錄
        //使用SqlSession執行完SQL之後需要關閉SqlSession
        sqlSession.close();
        System.out.println(order);//列印結果:Order [id=1, orderNo=aaaa, price=23.0]
    }
}

執行單元測試的結果:

  1、testGetOrderById方法執行查詢後返回一個null。

  2、testGetOrderById2方法和testGetOrderById3方法執行查詢後可以正常得到想要的結果。

四、總結

  上面的測試程式碼演示當實體類中的屬性名和表中的欄位名不一致時,使用MyBatis進行查詢操作時無法查詢出相應的結果的問題以及針對問題採用的兩種辦法:

  解決辦法一: 通過在查詢的sql語句中定義欄位名的別名,讓欄位名的別名和實體類的屬性名一致,這樣就可以表的欄位名和實體類的屬性名一一對應上了,這種方式是通過在sql語句中定義別名來解決欄位名和屬性名的對映關係的。

  解決辦法二: 通過<resultMap>來對映欄位名和實體類屬性名的一一對應關係。這種方式是使用MyBatis提供的解決方式來解決欄位名和屬性名的對映關係的。