MyBatis 是一款優秀的持久層框架,通過它可以更加便捷地和JDBC進行交互,而不需要進行繁瑣的數據庫連接配置與結果集的獲取。MyBatis 可以使用簡單的 XML 或註解來配置和映射原生類型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 對象)爲數據庫中的記錄。此外它還支持定製化 SQL、存儲過程以及高級映射。
使用步驟
1、使用Mybatis首先需要引入jar包,從其GitHub網站https://github.com/mybatis/mybatis-3/releases獲取其發佈版。之後解壓拷貝其jar包到所需的項目中,並添加爲依賴。
2、配置數據庫連接:接下來需要修改mybatis的配置文件,設置數據庫連接的驅動、url、用戶名和密碼:
<?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="logImpl" value="STDOUT_LOGGING" />
</settings>
<!--數據庫連接配置-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="" value=""/>
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<!--註冊映射配置-->
<mappers>
<mapper resource="com/dialogue/config/sql/Message.xml"/>
</mappers>
</configuration>
3、創建SqlSession:Mybatis對數據庫的操作是通過一個SqlSession對象來實現的,因此需要先創建一個DBUtils類來生成該對象,該類實現了getSession()方法用於讀取數據庫的配置文件並創建會話對象並返回
package com.dialogue.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
public class DBUtils {
public static SqlSession getSession() throws IOException {
//讀取配置文件中的數據庫連接信息
Reader reader= Resources.getResourceAsReader("com/dialogue/config/Configuration.xml");
//構建SQLSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);
//打開數據庫會話
SqlSession sqlSession=sqlSessionFactory.openSession();
return sqlSession;
}
}
4、配置數據庫操作文件:Mybatis將數據庫所要執行的操作和操作之後的結果集映射的規則都寫進了對應的xml文件,因此想要通過SqlSession進行數據庫操作,首先需要配置對應的xml文件。例如希望從數據庫中查詢message表的信息,表的字段如下。相應地我們創建了對應的JavaBean類Message,我們希望查詢表並返回所有Message對象的List
如下所示爲配置文件Message.xml,<mapper>內定義數據表和數據庫的映射關係,其中namespace類似於Java的package機制,用於防止命名衝突。<resultMap>標籤內定義數據類型的映射,type字段指明映射的Java類,id爲該映射的名。之後<id>和<result>標籤內定義數據庫的字段與Java類成員變量的映射,兩者的區別在於如果是主鍵的話用id,普通字段用result。其中column爲查詢數據庫的字段,如果select時起了別名,則按照別名來。jdbcType爲該字段的類型,property爲要映射到的Java類成員變量。
<select>標籤定義的是數據庫操作的配置,其id爲了區分不同的操作,resultMap爲剛纔定義的類型映射的id,標籤內爲要執行的sql操作
<?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">
<!--數據庫與Java類映射關係的配置-->
<resultMap type="com.dialogue.bean.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="getMessage" parameterType="long" resultMap="MessageResult">
SELECT ID,COMMAND,DESCRIPTION,CONTENT FROM message
</select>
</mapper>
將上面的配置文件Message.xml在主配置文件configuration.xml中進行註冊:
<mappers>
<mapper resource="com/dialogue/config/sql/Message.xml"/>
</mappers>
5、使用Mybatis查詢數據: 首先通過之前定義的DBUtils的getSession()獲取SQL Session對象,之後通過該對象調用selectList()進行查詢數據庫操作並返回結果對象的List。selectList()可以傳入參數"Message.getMessage"選擇xml配置文件中namespace爲Message中id爲getMessage的<select>操作標籤
public class MessageList {
List<Message> messageList=new ArrayList<>();
public MessageList() {
}
public List getMessageList() {
SqlSession sqlSession=null;
try {
//獲取會話對象
sqlSession= DBUtils.getSession();
//執行sql操作
messageList=sqlSession.selectList("Message.getMessage");
} catch (IOException e) {
e.printStackTrace();
}finally {
if (sqlSession!=null)
sqlSession.close(); //關閉會話對象
}
return messageList;
}
}
條件查詢
之前使用的select查詢將所有結果都返回了,如果希望按條件進行查詢,則需要在調用selectList()傳入查詢條件,但是該函數不支持傳入多個查詢參數,因此我們需要將查詢條件組合爲一個數據對象。在這裏創建一個message對象並將查詢條件command、description賦值給對象屬性,
public List getMessageList(String command,String description) {
SqlSession sqlSession=null;
//將查詢條件賦給對象
Message m=new Message();
m.setCommand(command);
m.setDescription(description);
try {
sqlSession= DBUtils.getSession();
//查詢時傳入參數條件
messageList=sqlSession.selectList("Message.getMessage",m);
......
那麼將查詢條件通過對象傳給查詢語句後,在xml文件中如何接收這些條件變量並拼接進查詢語句呢?這就需要使用OGNL。
OGNL
OGNL是Object-Graph Navigation Language的縮寫,它是一種功能強大的表達式語言,通過它簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉化等功能。它使用特定的表達式去存取對象的屬性。因爲只能傳入單個變量,所以在mybatis中的單個數據類型都用 _parameter 代替,而Java複合類型數據的獲取如下所示:
如果是自定義的類型可以直接通過屬性名獲取對象的屬性,例如下面的<select>查詢中使用parameterType設置傳入參數,之後可以在其中直接使用message對象的command、description屬性。不僅如此,可以直接在OGNL表達式中直接使用Java中的對象和函數,例如在<if test="">標籤中對查詢字段進行判斷,注意其中的符號&需要進行轉義爲XML標記&
Java中Prepare Statement通過?來進行佔位符,之後填充變量,在OGNL中使用 #{ command } 將變量填充到對應位置。
因此在Message.xml文件中修改之後按command和description條件的查詢<select>如下:
<select id="getMessage" parameterType="com.dialogue.bean.Message" resultMap="MessageResult">
SELECT ID,COMMAND,DESCRIPTION,CONTENT FROM message where 1=1
<if test="command !=null && ! command.isEmpty()">
AND COMMAND=#{command}
</if>
<if test="description !=null && ! description.isEmpty()">
AND DESCRIPTION like '%' #{description} '%'
</if>
</select>
打印SQL調試語句:Mybatis集成了sql語句的控制檯日誌輸出,在Configuration.xml文件中設置如下可開啓日誌輸出
<configuration>
<settings>
<!--設置控制檯輸出日誌-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
......
刪除操作
如下記錄一個刪除操作從請求到完成的整個過程,以記錄Java處理數據的文件結構
首先在jsp頁面內向服務器deleteOne的servlet發起請求並附帶要刪除的條目id
<a href="<%=basePath%>deleteOne?id=${message.getId()}">刪除</a>
接着請求到達DeleteOneServlet,在該servlet中接收前端傳來的參數,之後調用相應的Service完成刪除操作,最後再返回列表頁面
@WebServlet(name = "DeleteOneServlet",urlPatterns = "/deleteOne")
public class DeleteOneServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收參數
request.setCharacterEncoding("UTF-8");
String id=request.getParameter("id");
//調用service完成刪除操作
MaintainService maintainService=new MaintainService();
maintainService.deleteOne(id);
//刪除之後再跳轉到列表顯示頁面
request.getRequestDispatcher("/dialogueList").forward(request,response);
}
}
因此刪除的操作指令來到了MaintainService類中,在Service中完成數據的處理和相關判斷等操作,將處理好的數據傳給對應的DAO層進行刪除操作
public class MaintainService {
public void deleteOne(String id){
if (id!=null && !id.isEmpty()){ //數據判空
MessageDao messageDao =new MessageDao();
//將id數據類型轉換並傳給dao層方法
messageDao.deleteOne(Integer.valueOf(id));
}
}
}
此時操作請求來到了MessageDao,在DAO層完成數據對象的具體操作--刪除,這裏使用sqlSession.delete()進行數據庫的刪除操作,對應是Message.xml中<delete>標籤的deleteOne。由於其設置事務不自動提交,因此在操作完成後通過commit()將操作提交到數據庫
public class MessageDao {
public void deleteOne(int id){
SqlSession sqlSession=null;
try {
sqlSession=DBUtils.getSession();
sqlSession.delete("Message.deleteOne",id); //通過Mybatis完成刪除操作
sqlSession.commit(); //提交事務
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession!=null)
sqlSession.close();
}
}
......
在Mybatis配置文件Message.xml中的刪除操作定義如下,這樣一個刪除操作就真正交到了數據庫中完成了刪除操作。
<delete id="deleteOne" parameterType="int">
DELETE FROM message WHERE ID=#{_parameter}
</delete>
常用標籤
在Mybatis的配置文件中的常用標籤記錄如下
<where>標籤用於代替SQL語句中的WHERE關鍵字與查詢條件的拼接,如果直接使用WHERE後面在加條件時會有AND關鍵字需要拼接,但是如果WHERE之後直接跟AND條件會報錯,使用<where>標籤幫我們進行這個處理
<select id="getMessage" parameterType="com.dialogue.bean.Message" resultMap="MessageResult">
SELECT ID,COMMAND,DESCRIPTION,CONTENT FROM message
<where> <!--使用where標籤接條件-->
<if test="command !=null && ! command.isEmpty()">
AND COMMAND=#{command}
</if>
<if test="description !=null && ! description.isEmpty()">
AND DESCRIPTION like '%' #{description} '%'
</if>
</where>
</select>
<sql>標籤可以用於定義經常使用的常量,之後可以用<include>標籤引入,這樣代替經常出現的語句
<sql id="columns">ID,COMMAND,DESCRIPTION,CONTENT</sql>
<select id="getMessage" parameterType="com.dialogue.bean.Message" resultMap="MessageResult">
SELECT <include refid="columns"></include> FROM message
</select>
<update>標籤用於更新操作,對應在Java中通過update()調用該標籤的方法。在update多個值時,要用逗號分割,如果是最後一個逗號不處理會報錯,這裏就需要用到<set>標籤
<update id="update" parameterType="com.dialogue.bean.Message">
UPDATE message
<set>
<if test="command !=null && ! command.isEmpty()">
COMMAND=#{command},
</if>
<if test="description !=null && ! description.isEmpty()">
DESCRIPTION=#{description},
</if>
</set>
</update>
<trim>標籤用於給SQL語句添加或者刪除前後綴,prefix屬性爲要添加到前綴,suffix爲後綴。prefixOverrides爲要刪除的內容,例如句子中如果有AND,則刪除。suffixOverrides爲要刪除的後綴
<select id="mytrim">
<trim prefix="pre" suffix="after" prefixOverrides="AND" suffixOverrides=",">
......
</trim>
</select>
<choose>標籤類似於switch case選擇效果
<choose>
<when test=""></when>
<when test=""></when>
<otherwise></otherwise>
</choose>