一、MyBaits的增刪改查
1. 介紹
輸入映射
這里我先介紹一下輸入映射,是在映射文件中通過 parameterType
指定輸入?yún)?shù)的類型,類型可以是簡單類型、Hashmap
、POJO
的包裝類型。在實際操作中,一般我們會在 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ù),如果只是查詢操作,則可以不必提交
- 如果創(chuàng)建
openSession()
沒有加參數(shù),則在執(zhí)行 sql 的語句后提交數(shù)據(jù),可以使用sqlSession.commit()
- 如果創(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ù)
我們先來看一個情景,如果需要傳入 id
和 lastName
兩個參數(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}