做爲一個快樂的小碼農,在每個階段每每都在重複寫着不一樣版本的,學生管理,用戶管理,註冊登陸,從 JavaSE 的控制檯版,或者 GUI 版,再到 JavaWeb的 JSP版,再到純粹使用 HTML 做爲前端展現的版本,以及使用一個更新的技術,在此其中,咱們用過 txt 作數據庫,用 XML 也能夠,到如今經常使用的 MySQL,增刪改查一直是咱們必不可少的一部份內容,即便你不懂原理,即便你對這個技術的理解不是很深入,拿出你的增刪改查,噼裏啪啦就是一段亂敲,好歹仍是能讓你着手先作起來(固然,對技術的理解仍是很重要的),今天就和你們聊一聊 MyBatis 這門技術的 CURD (增刪改查)前端
在測試方法中,讀取配置文件,生產 SqlSession,釋放資源等等,在每一測試方法的時候,都是重複的,因此咱們徹底能夠提出出這一部分,防止大量的重複代碼java
@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() 這兩個方法,分別在咱們真正被測試的方法的先後執行sql
首先,在 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>
一、id 屬性,天然是對應的方法名,而因爲這裏,咱們並不須要拿到返回信息,因此這裏並無返回參數 resultType,而方法中的參數又爲一個 JavaBean 類,也就是User實體類,因此須要在標籤屬性中,添加一個 parameterType 屬性,其中須要指定這個實體類app
二、在文本中書寫插入的SQL語句,因爲實體類中已經快捷生成了對應的 get set 方法,所一可使用 #{}
的方式表明對應的值dom
三、提示,數據庫中id爲自增,因此並不須要設置 idide
因爲添加是更新類的語句,因此在執行插入語句後,須要提交事務,也就是執行對應的 commit方法,以提交更新操做,若沒有這一句,即便不會報錯,也沒法正常存入,會被回滾,且這個id被佔用測試
/** * 測試新增用戶 * @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); }
控制檯:優化
首先對於 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); }
執行效果
在 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>
/** * 測試新增用戶 * @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); }
接口中增長刪除方法
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>
/** * 測試刪除用戶 * @throws Exception */ @Test public void testDeleteUser() throws Exception{ //執行方法 userMapper.deleteUser(17); }
因爲查詢所有很是簡單,這裏就不展現了,基本流程都是同樣的
在 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>
/** * 測試模糊查詢 * @throws Exception */ @Test public void testFindByName() throws Exception{ List<User> users = userMapper.findByName("%張%"); for (User user : users){ System.out.println(user); } }
在使用模糊查詢的時候,咱們須要在查詢條件的兩側拼接兩個 「%」 字符串,這個時候有兩種解決方案,一種就是像在我上述代碼中,在測試時將字符串補充完整,還有一種方式就是 使用 ${}
,它在 SQL配置文件中表明一個 「拼接符號」 ,也就是說能夠這樣寫 SQL語句
select * from user where username like '%{value}'
可接受的類型有,普通類型(此狀況下{}內部只能寫value),JavaBean,HashMap
可是使用 %{}
拼接字符串的時候,會引發 SQL注入,因此不是很推薦使用
Mapper 的輸入映射樣例中,咱們對於基本數據類型和基本數據包裝類,都有了必定的瞭解,而下面咱們來聊一聊關於相對複雜的一種狀況,那就是自定義包裝類
先講一個需求:仍是關於用戶的查詢,可是查詢條件複雜了一些,不只僅侷限於用戶的信息,並且可能還包括訂單,購物車,或者與用戶一些行爲相關的信息,那麼如何實現這樣一種需求呢?
那咱們想,可不能夠,在 User 類中增長一些咱們須要的信息
package cn.ideal.domain; public class QueryUserVo { private UserInstance userInstance; public UserInstance getUserInstance() { return userInstance; } public void setUserInstance(UserInstance userInstance) { this.userInstance = userInstance; } //其餘查詢條件,例如訂單,購物車等等 }
咱們這裏使用用戶的性別以及對姓名的模糊查詢,來寫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給省略了
/** * 包裝對象做爲查詢參數 * @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); } }
若是文章中有什麼不足,歡迎你們留言指正,感謝你們的支持!
若是能幫到你的話,那就來關注我吧!若是您更喜歡微信文章的閱讀方式,能夠關注個人公衆號
在這裏的咱們素不相識,卻都在爲了本身的夢而努力 ❤一個堅持推送原創開發技術文章的公衆號:理想二旬不止