MyBaits | 對映檔案之引數處理

weixin_34320159發表於2018-07-26
8213676-810d37d8db2d0710.jpg

一、MyBaits的增刪改查

1. 介紹

輸入對映

這裡我先介紹一下輸入對映,是在對映檔案中通過 parameterType 指定輸入引數的型別,型別可以是簡單型別、HashmapPOJO 的包裝型別。在實際操作中,一般我們會在 parameterType 屬性中傳入 POJO 的類名。如果是通過輸入條件進行查詢,我們只需要傳入對應的 POJO 中的屬性即可

輸出對映

輸出對映就是 sql 語句查詢結束後返回的結果型別,在對映檔案中通過 resultType 來顯示輸出的結果型別,不過一般可以不用設定 resultType,MyBatis 會自己幫我們輸出。另外還可以使用 resultMap,這種配置方式可以用於各種複雜的對映方式,比如一對多,多對多等等,在後面的文章中會加以介紹

2. 使用 resultType 配置實現增刪改查

①.首先我們定義一個 POJO 類:Employee.java

public class Employee {

    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;

    public Integer getId() {
        return id;
    }

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


②. 然後我們定義一個介面類:EmployeeMapper.java,該介面包含了對 Employee 的增刪改查操作

public interface EmployeeMapper {
        
    public void addEmployee(Employee employee);
    
    public void updateEmployee(Employee employee);
    
    public long deleteEmployee(Integer id);
    
    public Employee getEmployee(Integer id);
    
}


③. 配置 EmployeeMapper.xml,這裡我就只對增加操作加以說明,其他三種操作與之類似

<mapper namespace="edu.just.mybatis.dao.EmployeeMapper">
    <select id="getEmployee" resultType="edu.just.mybatis.bean.Employee">
        select id, last_name lastName, email, gender from employee where id = #{id}
    </select>
</mapper>
  • namespace:指定為你要實現的介面的全類名
  • id:唯一標識 resultType: 返回值型別
  • parameterType:是傳入的引數的型別,可以使用別名,如果返回的是一個集合, 則寫集合中元素的型別,比如 Employee, mybaits 會自動幫你把該類的物件放入集合中並返回
  • resultType:返回查詢結果的型別,沒有指定別名的情況下,使用全類名,當然也可以省略

④. 寫一個測試語句,使用介面定義的方法

@Test
public void testGetEmployee() throws IOException {
    //1. 獲取 sqlSessionFactory 物件
    SqlSessionFactory sqlSessionFactory = getSqlSessionFactoty();
    
    //2. 獲取 sqlSession 物件
    SqlSession sqlSession = sqlSessionFactory.openSession();
        
    try {
        //3. 獲取介面的實現類物件, 會為介面自動建立一個代理物件, 代理物件去執行增、刪、改、查
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee = employeeMapper.getEmployee(1);
        System.out.println(employee);
    } finally {
        sqlSession.close();
    }
}

這裡需要注意的是:如果涉及到對資料庫資料本身的操作,針對增刪改,每次執行完 sql 語句都需要提交資料,如果只是查詢操作,則可以不必提交

  1. 如果建立 openSession() 沒有加引數,則在執行 sql 的語句後提交資料,可以使用 sqlSession.commit()
  2. 如果建立 openSession(true), 則不需要提交資料

3. 其他情況

3.1 獲取自增主鍵的值

在配置檔案中將 useGeneratedKeys 屬性設定為 true,同時 keyProperty 屬性指定將獲取的主鍵值賦給 JavaBean 的哪個屬性

<insert id="addEmployee" parameterType="Employee" useGeneratedKeys="true" keyProperty="id">
    Insert into employee(last_name, email, gender) values(#{lastName}, #{email}, #{gender})
</insert>

該配置表示將主鍵值賦給 Employee 的 id 屬性,在測試檔案中如果輸出 id,即為當前查詢結果的主鍵值

3.2 返回 List 集合的操作

首先在介面類中新增返回集合的方法

public List<Employee> getEmployees(String lastName);

然後在 sql 對映檔案中配置,此時 resultType 的型別依舊是 Employee,因為對應的是集合中引數的型別

<select id="getEmployees" resultType="Employee">
    select * from employee where last_name like #{lastName}
</select>

輸出如下

[Employee [id=7, lastName=null, email=lkj@123.com, gender=1], 
Employee [id=13, lastName=null, email=lkj@123.com, gender=2], 
Employee [id=14, lastName=null, email=lkj@123.com, gender=2], 
Employee [id=15, lastName=null, email=lkj@123.com, gender=2], 
Employee [id=16, lastName=null, email=lkj@123.com, gender=2]]


3.3 返回一個封裝多個記錄的 Map 集合

@MapKey() 告訴 mybatis 封裝這個 map 時候使用哪個POJO 屬性作為 key

@MapKey("id")
public Map<Integer, Employee> getEmployee3(Integer id);

配置 sql 對映檔案,注意此時 resultType 型別依然是 Employee,即表示返回的型別依舊是 Employee

<select id="getEmployee3" resultType="Employee">
    select id, last_name lastName, email, gender from employee where id > #{id}
</select>

輸出

{16=Employee [id=16, lastName=lkj, email=lkj@123.com, gender=2], 
17=Employee [id=17, lastName=lkj, email=lkj@123.com, gender=2], 
2=Employee [id=2, lastName=Peter, email=peter@qq.com, gender=1], 
19=Employee [id=19, lastName=lkj, email=lkj@123.com, gender=2], 
20=Employee [id=20, lastName=lkj, email=lkj@123.com, gender=2]}


二、對引數進行處理

1. 傳入單個引數

傳入單個引數時,${xxx} 裡面的引數名和屬性名無關,比如你佔位符設定為 #{id},此時當然可以查詢出結果。但是如果你設定為 #{id123},同樣查詢出結果, 但是如果什麼都不填, 則會報錯

<select id="getEmployee" resultType="edu.just.mybatis.bean.Employee">
       select id, last_name lastName, email, gender from employee where id = #{id123} 
</select>


2. 傳入多個引數

我們先來看一個情景,如果需要傳入 idlastName 兩個引數

public Employee getEmployee2(Integer id, String lastName);

sql 的配置檔案是這樣設定的

<select id="getEmployee2" resultType="employee">
    select id, last_name lastName, email, gender from employee where 
      id = #{id} and last_name = #{lastName}
</select>

此時會出這樣的錯誤:Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]

原因就是當 sql 語句傳入不止一個引數時, MyBatis 會做特殊處理, 多個引數會被封裝到一個 Map 物件 map 中,當你每傳入一個引數,map 物件會將引數以鍵為 param1, param2...paramN,值為你 傳入的引數的值 的形式來儲存資料,此時如果你傳入的還是類似 #{id}#{name} 之類的引數,那麼肯定會報錯

解決方案

方案一
我們以上述的例子為例,我們可以直接傳入 #{param1},#{param2} 等引數

<select id="getEmployee2" resultType="employee">
    select id, last_name lastName, email, gender from employee where 
        id = #{param1} and last_name = #{param2}
</select>

方案二
我們在介面定義的方法處,使用 @Param() 標註給方法中的引數起名字,其實本質上也是放在 Map 和物件 map 中

public Employee getEmployee2(@Param("id")Integer id, @Param("lastName")String lastName);

我們可以這樣給傳入的引數賦值,這時 map 中的 key 變為了 id, lastName, param1, param2。因此我們可以直接在 #{} 中傳入我們自己命名的值。當然就算傳入 #{param1} 之類的也是可以的。

<select id="getEmployee2" resultType="employee">
    select id, last_name lastName, email, gender from employee where 
        id = #{id} and last_name = #{lastName}
</select>


三、${} 和 #{} 的區別

#{}:是以預編譯的形式,將引數設定到 sql 語句中,多用於 where 語句後面的填充位,
${}:取出的值直接拼接在 sql 語句中,多用於分表的 sql 語句,會有執行緒安全的問題

關於 #{} 的使用我不加以贅述,下面舉例說明 ${} 用於分表的操作語句

select * from ${year}_table where xxx
select * from table order by ${xxx} ${xxx}

相關文章