Mybatis入門學習
為什麽要學習Mybatis?
其實一句話就夠了,web開發需要框架來提高效率,而Mybatis逐漸替代hibernate成為主流,所以必須掌握。這是從需求來講。
Mybatis與JDBC相比,除了因為框架開銷而導致性能略有下降,其他方面都要好很多。
我體會到的最省事兒的地方就是,把ResultSet循環傳入new的實體類中這部分代碼簡化到了sql配置文件(xml)中。
另外,jdbc的sql都在class中,如果需要改sql語句,還得找到源文件去修改sql,然後編譯成class再放到服務器上,然後重啟生效。而Mybatis只需要在配置文件中修改CRUD標簽中的sql就好了。
下面以一個小項目的實現來學習Mybatis。本文只實現全部查詢的操作,至於動態SQL拼接、分頁、攔截器等,將在以後的 Mybatis進階學習 中總結。
【準備工作】
eclipse、tomcat、navicat等軟件就不說了。
首先,展示一下慕課網上下載的前端頁面:
其次,從https://github.com/mybatis/mybatis-3上下載最新的RELEASE版本(mybatis-3.4.5)和相應的資源包(mybatis-3-mybatis-3.4.5),還需要下載mysql驅動包(mysql-connector-java-5.1.42)和JSP標簽庫的兩個jar(jstl.jar和standard.jar)。
導入jar包之後就可以開始項目了。
【項目開發】
一、設計數據庫
我個人的習慣是先設計數據庫,參照前端頁面(其實就是需求)設計好數據庫test_mybatis,其中message表包含字段id(int)、command(varchar)、description(varchar)、content(varchar)。
插入數據的sql代碼如下:
INSERT INTO `message` VALUES (1, ‘查看‘, ‘精彩內容‘, ‘精彩內容‘); INSERT INTO `message` VALUES (2, ‘段子‘, ‘精彩段子‘, ‘如果你的月薪是3000塊錢,請記得分成五份,一份用來買書,一份給家人,一份給女朋友買化妝品和衣服,一份請朋友們吃飯,一份作為同事的各種婚喪嫁娶的份子錢。剩下的2999塊錢藏起來,不要告訴任何人‘); INSERT INTO `message` VALUES (3, ‘新聞‘, ‘今日頭條‘, ‘7月17日,馬來西亞一架載有298人的777客機在烏克蘭靠近俄羅斯邊界墜毀。另據國際文傳電訊社消息,墜毀機型為一架波音777客機,機載約280名乘客和15個機組人員。\r\n烏克蘭空管部門隨後證實馬航MH17航班墜毀。烏克蘭內政部幕僚表示,這一航班在頓涅茨克地區上空被擊落。馬來西亞航空公司確認,該公司從阿姆斯特丹飛往吉隆坡的MH17航班失聯,並稱最後與該客機取得聯系的地點在烏克蘭上空。圖為馬航客機墜毀現場。‘); INSERT INTO `message` VALUES (4, ‘娛樂‘, ‘娛樂新聞‘, ‘昨日,鄧超在微博分享了自己和孫儷的書法。夫妻同樣寫幸福,但差距很大。鄧超自己都忍不住感慨字醜:左邊媳婦寫的。右邊是我寫的。看完我再也不幸福了。‘); INSERT INTO `message` VALUES (5, ‘電影‘, ‘近日上映大片‘, ‘《忍者神龜》[2]真人電影由美國派拉蒙影業發行,《洛杉磯之戰》導演喬納森·裏貝斯曼執導。 \r\n片中四只神龜和老鼠老師都基於漫畫和卡通重新繪制,由動作捕捉技術實現。\r\n其中皮特·普勞澤克飾演達芬奇(武器:武士刀),諾爾·費舍飾演米開朗基羅(武器:雙節棍),阿倫·瑞奇森飾演拉斐爾(武器:鐵叉),傑瑞米·霍華德飾演多拉泰羅(武器:武士棍)。\r\n該片計劃於2014年8月8日在北美上映。‘); INSERT INTO `message` VALUES (6, ‘彩票‘, ‘中獎號碼‘, ‘查啥呀查,你不會中獎的!‘);
二、配置Mybatis
1.首先需要寫好Message實體類
public class Message { private int id; private String command; private String description; private String content; public Message(){} public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCommand() { return command; } public void setCommand(String command) { this.command = command; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
2.接下來配置Configuration.xml和Message.xml
前者是Mybatis的核心配置文件,主要用來連接MySQL數據庫和映射Message.xml。
後者用來編寫sql語句和把查詢的結果集與實體類各屬性(4個字段)映射。
沒必要自己把這兩個xml敲出來,可以在資源包mybatis-3-mybatis-3.4.5\src\test\java\org\apache\ibatis\submitted\complex_property中得到Configuration.xml和User.xml,把相應代碼修改後就可以使用了。
Configuration.xml配置文件:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- <settings> <setting name="useGeneratedKeys" value="false"/> <setting name="useColumnLabel" value="true"/> </settings> <typeAliases> <typeAlias alias="UserAlias" type="org.apache.ibatis.submitted.complex_property.User"/> </typeAliases> --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"> <property name="" value=""/> </transactionManager> <dataSource type="UNPOOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/test_mybatis"/> <property name="username" value="root"/> <property name="password" value="[email protected]#$"/> </dataSource> </environment> </environments> <mappers> <mapper resource="config/sqlxml/Message.xml"/> </mappers> </configuration>
Message.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="Message"> <resultMap type="javabean.Message" id="MessageResult"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="command" jdbcType="VARCHAR" property="command"/> <result column="description" jdbcType="VARCHAR" property="description"/> <result column="content" jdbcType="VARCHAR" property="content"/> </resultMap> <select id="getByName" resultMap="MessageResult"> select id,command,description,content from message where 1=1 </select> </mapper>
三、實現數據庫操作
編寫DBUtil類和MessageDAO類(由於項目簡單,沒有寫service層和dao與service的Impl層)。前者連接MySQL並返回SqlSession對象,後者實現查詢操作。
註意要在dao中處理異常,並在finally中關閉SqlSession。
這一步完成後,可以寫一個測試類,檢驗代碼是否正確。
public class DBUtil { public SqlSession getSqlSession() throws IOException{ //通過配置文件Configuration.xml獲取數據庫連接信息 Reader reader = Resources.getResourceAsReader("config/Configuration.xml"); //通過配置信息構建一個SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); //通過sqlSessionFactory打開一個數據庫會話 SqlSession sqlSession = sqlSessionFactory.openSession(); return sqlSession; } }
public class MessageDAO { /** * 查詢列表信息(方法名是為多選擇查詢起的,會在以後的文章中實現) */ public List<Message> getByName(String command, String description){ DBUtil dbUtil = new DBUtil(); SqlSession sqlSession = null; List<Message> messageList = new ArrayList<Message>(); try { sqlSession = dbUtil.getSqlSession(); //通過sqlSession執行SQL語句,需要sql的配置文件Message.xml messageList = sqlSession.selectList("Message.getByName"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if(sqlSession!=null){ sqlSession.close(); } } return messageList; } }
四、編寫servlet和JSP相應代碼
1.servlet類和web.xml中的配置
@SuppressWarnings("serial") public class ListServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //編碼一律用utf-8 req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); //接收頁面參數的值 String command = req.getParameter("command"); String description = req.getParameter("description"); /*一開始總打印null,原來是name放錯位置了,應該放到input裏!!! System.out.println(command); System.out.println(description);*/ //按command和description查詢列表信息 MessageDAO messageDAO = new MessageDAO(); List<Message> messageList = messageDAO.getByName(command, description); //向頁面傳值 req.setAttribute("command", command); req.setAttribute("description", description); req.setAttribute("messageList", messageList); //頁面跳轉 /*因為要傳遞參數,而不用重定向*/ req.getRequestDispatcher("/jsp/back/list.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>testMybatis</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>ListServlet</servlet-name> <servlet-class>servlet.ListServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ListServlet</servlet-name> <url-pattern>/list.action</url-pattern> </servlet-mapping> </web-app>
2.JSP頁面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <base href="<%=basePath%>"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="X-UA-Compatible"content="IE=9; IE=8; IE=7; IE=EDGE" /> <title>內容列表頁面</title> <link href="css/all.css" rel="stylesheet" type="text/css" /> </head> <body style="background: #e1e9eb;"> <form action="list.action" id="mainForm" method="post"> <div class="right"> <div class="current">當前位置:<a href="javascript:void(0)" style="color:#6E6E6E;">內容管理</a> > 內容列表</div> <div class="rightCont"> <p class="g_title fix">內容列表 <a class="btn03" href="#">新 增</a> <a class="btn03" href="#">刪 除</a></p> <table class="tab1"> <tbody> <tr> <td width="90" align="right">指令名稱:</td> <td> <input name="command" type="text" class="allInput" value="${command}"/> </td> <td width="90" align="right">描述:</td> <td> <input name="description" type="text" class="allInput" value="${description}"/> </td> <td width="85" align="right"><input type="submit" class="tabSub" value="查 詢" /></td> </tr> </tbody> </table> <div class="zixun fix"> <table class="tab2" width="100%"> <tbody> <tr> <th><input type="checkbox" id="all" onclick="#"/></th> <th>序號</th> <th>指令名稱</th> <th>描述</th> <th>操作</th> </tr> <c:forEach items="${messageList}" var="message" varStatus="status"> <tr <c:if test="${status.index % 2 !=0}">style="background-color:#ECF6EE;"</c:if>> <td><input type="checkbox" /></td> <td>${status.index + 1}</td> <td>${message.command }</td> <td>${message.description }</td> <td> <a href="#">修改</a> <a href="#">刪除</a> </td> </tr> </c:forEach> </tbody> </table> <div class=‘page fix‘> 共 <b>4</b> 條 <a href=‘###‘ class=‘first‘>首頁</a> <a href=‘###‘ class=‘pre‘>上一頁</a> 當前第<span>1/1</span>頁 <a href=‘###‘ class=‘next‘>下一頁</a> <a href=‘###‘ class=‘last‘>末頁</a> 跳至 <input type=‘text‘ value=‘1‘ class=‘allInput w28‘ /> 頁 <a href=‘###‘ class=‘go‘>GO</a> </div> </div> </div> </div> </form> </body> </html>
【總結】
本文主要用來記錄和復習大致過程,因此很多細節沒有過多說明。
且由於個人水平有限,很多地方都只有最簡單的講解,而且難免有錯,在深入學習之後會做出修改和說明。
PS:寫博客真的似乎有點兒浪費時間啊,可能我太不老練吧,感覺有這一個多小時可以學更多東西或者復習所做的項目了。。
Mybatis入門學習