MyBaits | 映射文件之參數(shù)處理

一、MyBaits的增刪改查

1. 介紹

輸入映射

這里我先介紹一下輸入映射,是在映射文件中通過 parameterType 指定輸入?yún)?shù)的類型,類型可以是簡單類型、HashmapPOJO 的包裝類型。在實際操作中,一般我們會在 parameterType 屬性中傳入 POJO 的類名。如果是通過輸入條件進行查詢,我們只需要傳入對應(yīng)的 POJO 中的屬性即可

輸出映射

輸出映射就是 sql 語句查詢結(jié)束后返回的結(jié)果類型,在映射文件中通過 resultType 來顯示輸出的結(jié)果類型,不過一般可以不用設(shè)置 resultType,MyBatis 會自己幫我們輸出。另外還可以使用 resultMap,這種配置方式可以用于各種復(fù)雜的映射方式,比如一對多,多對多等等,在后面的文章中會加以介紹

2. 使用 resultType 配置實現(xiàn)增刪改查

①.首先我們定義一個 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:指定為你要實現(xiàn)的接口的全類名
  • id:唯一標(biāo)識 resultType: 返回值類型
  • parameterType:是傳入的參數(shù)的類型,可以使用別名,如果返回的是一個集合, 則寫集合中元素的類型,比如 Employee, mybaits 會自動幫你把該類的對象放入集合中并返回
  • resultType:返回查詢結(jié)果的類型,沒有指定別名的情況下,使用全類名,當(dāng)然也可以省略

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

@Test
public void testGetEmployee() throws IOException {
    //1. 獲取 sqlSessionFactory 對象
    SqlSessionFactory sqlSessionFactory = getSqlSessionFactoty();
    
    //2. 獲取 sqlSession 對象
    SqlSession sqlSession = sqlSessionFactory.openSession();
        
    try {
        //3. 獲取接口的實現(xiàn)類對象, 會為接口自動創(chuàng)建一個代理對象, 代理對象去執(zhí)行增、刪、改、查
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee = employeeMapper.getEmployee(1);
        System.out.println(employee);
    } finally {
        sqlSession.close();
    }
}

這里需要注意的是:如果涉及到對數(shù)據(jù)庫數(shù)據(jù)本身的操作,針對增刪改,每次執(zhí)行完 sql 語句都需要提交數(shù)據(jù),如果只是查詢操作,則可以不必提交

  1. 如果創(chuàng)建 openSession() 沒有加參數(shù),則在執(zhí)行 sql 的語句后提交數(shù)據(jù),可以使用 sqlSession.commit()
  2. 如果創(chuàng)建 openSession(true), 則不需要提交數(shù)據(jù)

3. 其他情況

3.1 獲取自增主鍵的值

在配置文件中將 useGeneratedKeys 屬性設(shè)置為 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,即為當(dāng)前查詢結(jié)果的主鍵值

3.2 返回 List 集合的操作

首先在接口類中添加返回集合的方法

public List<Employee> getEmployees(String lastName);

然后在 sql 映射文件中配置,此時 resultType 的類型依舊是 Employee,因為對應(yīng)的是集合中參數(shù)的類型

<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]}


二、對參數(shù)進行處理

1. 傳入單個參數(shù)

傳入單個參數(shù)時,${xxx} 里面的參數(shù)名和屬性名無關(guān),比如你占位符設(shè)置為 #{id},此時當(dāng)然可以查詢出結(jié)果。但是如果你設(shè)置為 #{id123},同樣查詢出結(jié)果, 但是如果什么都不填, 則會報錯

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


2. 傳入多個參數(shù)

我們先來看一個情景,如果需要傳入 idlastName 兩個參數(shù)

public Employee getEmployee2(Integer id, String lastName);

sql 的配置文件是這樣設(shè)置的

<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]

原因就是當(dāng) sql 語句傳入不止一個參數(shù)時, MyBatis 會做特殊處理, 多個參數(shù)會被封裝到一個 Map 對象 map 中,當(dāng)你每傳入一個參數(shù),map 對象會將參數(shù)以鍵為 param1, param2...paramN,值為你 傳入的參數(shù)的值 的形式來保存數(shù)據(jù),此時如果你傳入的還是類似 #{id}#{name} 之類的參數(shù),那么肯定會報錯

解決方案

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

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

方案二
我們在接口定義的方法處,使用 @Param() 標(biāo)注給方法中的參數(shù)起名字,其實本質(zhì)上也是放在 Map 和對象 map 中

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

我們可以這樣給傳入的參數(shù)賦值,這時 map 中的 key 變?yōu)榱?id, lastName, param1, param2。因此我們可以直接在 #{} 中傳入我們自己命名的值。當(dāng)然就算傳入 #{param1} 之類的也是可以的。

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


三、${} 和 #{} 的區(qū)別

#{}:是以預(yù)編譯的形式,將參數(shù)設(shè)置到 sql 語句中,多用于 where 語句后面的填充位,
${}:取出的值直接拼接在 sql 語句中,多用于分表的 sql 語句,會有線程安全的問題

關(guān)于 #{} 的使用我不加以贅述,下面舉例說明 ${} 用于分表的操作語句

select * from ${year}_table where xxx
select * from table order by ${xxx} ${xxx}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容