MyBatis入門到CURD
作爲一個快樂的小碼農,在每一個階段往往都在重複寫着不同版本的,學生管理,用戶管理,註冊登錄,從 JavaSE 的控制檯版,或者 GUI 版,再到 JavaWeb的 JSP版,再到純粹使用 HTML 作爲前端展示的版本,以及使用一個更新的技術,在此其中,我們用過 txt 做數據庫,用 XML 也可以,到現在常用的 MySQL,增刪改查一直是我們必不可少的一部分內容,即使你不懂原理,即使你對這個技術的理解不是很深刻,拿出你的增刪改查,噼裏啪啦就是一段亂敲,好歹還是能讓你着手先做起來(當然,對技術的理解還是很重要的),今天就和大家聊一聊 MyBatis 這門技術的 CURD (增刪改查)
優化測試方法
在測試方法中,讀取配置文件,生產 SqlSession,釋放資源等等,在每一測試方法的時候,都是重複的,所以我們完全可以提出出這一部分,防止大量的重複代碼
@Before
public void init() throws Exception{
//讀取配置文件
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//創建SqlSessionFactory工廠
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
//使用工廠生產SqlSession對象
sqlSession= factory.openSession();
//使用SqlSession創建Mapper接口的代理對象
userMapper = sqlSession.getMapper(UserMapper.class);
}
@After
public void destroy() throws Exception{
sqlSession.close();
inputStream.close();
}
在這兩個方法上增加 @Before 和 @Aftrer 註解,就可以保證,init() 和 destory() 這兩個方法,分別在我們真正被測試的方法的前後執行
(一) 增添操作
(1) 編寫代碼
首先,在 UserMapper 接口中 增加對應的方法
public interface UserMapper {
/**
* 增加用戶
* @param user
*/
void addUser(User user);
}
接着,在SQL映射文件中,增加新增的映射配置,這些有關內容放在 <insert></insert>
標籤對中,具體代碼如下
<insert id="addUser" parameterType="cn.ideal.domain.User">
insert into user(username,telephone,birthday,gender,address)values(#{username},# {telephone},#{birthday},#{gender},#{address})
</insert>
(2) 說明:
1、id 屬性,自然是對應的方法名,而由於這裏,我們並不需要拿到返回信息,所以這裏並沒有返回參數 resultType,而方法中的參數又爲一個 JavaBean 類,也就是User實體類,所以需要在標籤屬性中,添加一個 parameterType 屬性,其中需要指定這個實體類
2、在文本中書寫插入的SQL語句,由於實體類中已經快捷生成了對應的 get set 方法,所一可以使用 #{}
的方式代表對應的值
3、提示,數據庫中id爲自增,所以並不需要設置 id
(3) 注意:
由於添加是更新類的語句,所以在執行插入語句後,需要提交事務,也就是執行對應的 commit方法,以提交更新操作,若沒有這一句,即使不會報錯,也無法正常存入,會被回滾,且這個id被佔用
(4) 測試代碼:
/**
* 測試新增用戶
* @throws Exception
*/
@Test
public void testUpdateUser() throws Exception{
User user = new User();
user.setId(17);
user.setUsername("修改");
user.setTelephone("18899999999");
user.setBirthday(new Date());
user.setGender("女");
user.setAddress("廣州");
//執行方法
userMapper.updateUser(user);
}
(5) 執行結果:
控制檯:
(6) 獲取新增用戶的id值
首先對於 MySQL自增主鍵來說,在執行 insert語句之前,MySQL 會自動生成一個自增主鍵,insert執行後,通過 SELECT LAST_INSERT_ID()
可以獲取這條剛插入記錄的自增主鍵
在 SQL 映射配置文件中,需要藉助 <selectKey></selectKey>
標籤,有一個屬性比較特殊,order 屬性,它代表着相對於插入操作的執行時間,before-之前,after-之後
注:該標籤插入到 <select></select>
中
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID();
</selectKey>
測試一下
@Test
public void testAddUser() throws Exception{
User user = new User();
user.setUsername("增加");
user.setTelephone("12266660000");
user.setBirthday(new Date());
user.setGender("男");
user.setAddress("珠海");
System.out.println("執行插入前" + user);
//執行方法
userMapper.addUser(user);
System.out.println("執行插入後" + user);
}
執行效果
(二) 修改操作
(1) 編寫代碼
在 UserMapper 接口中增加修改方法
public interface UserMapper {
/**
* 更新用戶
* @param user
*/
void updateUser(User user);
}
在 SQL 映射文件中增加語句,內容包括在 <update></update>
中,需要注意的基本與添加操作是一致的
<update id="updateUser" parameterType="cn.ideal.domain.User">
update user set username=#{username},telephone=#{telephone},birthday=#{birthday},gender=#{gender},address=#{address} where id=#{id}
</update>
(2) 測試代碼
/**
* 測試新增用戶
* @throws Exception
*/
@Test
public void testAddUser() throws Exception{
User user = new User();
user.setUsername("增加");
user.setTelephone("12266668888");
user.setBirthday(new Date());
user.setGender("女");
user.setAddress("成都");
//執行方法
userMapper.addUser(user);
}
(3) 執行效果
(三) 刪除操作
(1) 編寫代碼
接口中增加刪除方法
public interface UserMapper {
/**
* 刪除用戶
* @param uid
*/
void deleteUser(Integer uid);
}
在SQL映射文件中,使用 <delete></delete>
標籤對進行內容的書寫,需要注意的是,由於我們傳入的參數是一個 Integer類型的用戶id,所以參數類型的值爲 parameterType
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
(2) 測試代碼
/**
* 測試刪除用戶
* @throws Exception
*/
@Test
public void testDeleteUser() throws Exception{
//執行方法
userMapper.deleteUser(17);
}
(3) 執行效果
(四) 模糊查詢
由於查詢全部非常簡單,這裏就不展示了,基本流程都是一樣的
(1) 編寫代碼
在 UserMapper 接口中編寫方法
public interface UserMapper {
/**
* 通過姓名模糊查詢
* @param username
* @return
*/
List<User> findByName(String username);
}
在 SQL 映射文件中新增查詢語句
<select id="findByName" parameterType="java.lang.String" resultType="cn.ideal.domain.User">
select * from user where username like #{username}
</select>
(2) 測試代碼
/**
* 測試模糊查詢
* @throws Exception
*/
@Test
public void testFindByName() throws Exception{
List<User> users = userMapper.findByName("%張%");
for (User user : users){
System.out.println(user);
}
}
(3) 注意
在使用模糊查詢的時候,我們需要在查詢條件的兩側拼接兩個 “%” 字符串,這個時候有兩種解決方案,一種就是像在我上述代碼中,在測試時將字符串補充完整,還有一種方式就是 使用 ${}
,它在 SQL配置文件中代表一個 “拼接符號” ,也就是說可以這樣寫 SQL語句
select * from user where username like '%{value}'
可接受的類型有,普通類型(此情況下{}內部只能寫value),JavaBean,HashMap
但是使用%{}
拼接字符串的時候,會引起 SQL注入,所以不是很推薦使用
(4) 執行效果
(五) 自定義包裝類作爲查詢條件
Mapper 的輸入映射樣例中,我們對於基本數據類型和基本數據包裝類,都有了一定的瞭解,而下面我們來聊一聊關於相對複雜的一種情況,那就是自定義包裝類
先講一個需求:還是關於用戶的查詢,但是查詢條件複雜了一些,不僅僅侷限於用戶的信息,而且可能還包括訂單,購物車,或者與用戶一些行爲相關的信息,那麼如何實現這樣一種需求呢?
那我們想,可不可以,在 User 類中增加一些我們需要的信息
- 從代碼的角度來看,在 User 中添加的字段與數據庫不一定能對應起來,在原來的基礎上做修改,就會影響 User 作爲數據庫映射對象的功能,所以我們可以創建一個 UserInstance 類,繼承 User類就可以在其中爲某些業務添加一些不屬於數據庫的字段了
(1) 定義包裝類
package cn.ideal.domain;
public class QueryUserVo {
private UserInstance userInstance;
public UserInstance getUserInstance() {
return userInstance;
}
public void setUserInstance(UserInstance userInstance) {
this.userInstance = userInstance;
}
//其他查詢條件,例如訂單,購物車等等
}
(2) 配置 Mapper 文件
我們這裏使用用戶的性別以及對姓名的模糊查詢,來寫SQL 當然,你也可以自己通過別的信息寫SQL
<select id="findUserByVo" parameterType="cn.ideal.domain.QueryUserVo" resultType="cn.ideal.domain.UserInstance">
select * from user where user.gender=#{userInstance.gender} and user.username like #{userInstance.username}
</select>
在QueryUserVo 中,封裝的是查詢信息的各種對象,爲什麼上述代碼可以直接通過 userInstance.gender 直接取出對應的屬性,這種方式叫做 OGNL 表達式,在類中 我們的寫法通常是 user.getUsername
但在寫法上,OGNL 表達式將get給省略了
(3) 測試代碼
/**
* 包裝對象作爲查詢參數
* @throws Exception
*/
@Test
public void testFindUserByVo() throws Exception{
//創建包裝對象,設置查詢條件
QueryUserVo queryUserVo = new QueryUserVo();
UserInstance userInstance = new UserInstance();
userInstance.setGender("女");
userInstance.setUsername("%張%");
queryUserVo.setUserInstance(userInstance);
//調用 UserMapper 的方法
List<UserInstance> userInstances
= userMapper.findUserByVo(queryUserVo);
for (UserInstance u : userInstances){
System.out.println(u);
}
}
(4) 執行效果
結尾
如果文章中有什麼不足,歡迎大家留言指正,感謝大家的支持!
如果能幫到你的話,那就來關注我吧!如果您更喜歡微信文章的閱讀方式,可以關注我的公衆號
在這裏的我們素不相識,卻都在爲了自己的夢而努力 ❤
一個堅持推送原創開發技術文章的公衆號:理想二旬不止