Mybatis學習總結

席潤發表於2019-02-13

核心配置檔案

一、建立配置層config,其下放置核心配置檔案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>
  <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/micro_message"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
      </dataSource>
    </environment>
  </environments>

  //對映到SQL配置檔案
  <mappers>
    <mapper resource="com/imooc/config/sqlxml/Message.xml"/>
    <mapper resource="com/imooc/config/sqlxml/Command.xml"/>
    <mapper resource="com/imooc/config/sqlxml/CommandContent.xml"/>
  </mappers>
</configuration>
複製程式碼

資料庫互動最重要的物件SqlSession:

作用: 1、向SQL語句傳入引數 2、執行SQL 3、獲取執行SQL語句的結果 4、事務控制

如何得到SqlSession: 1、通過配置檔案獲取資料庫連線相關資訊 2、通過配置資訊構建SqlSessionFactory 3、通過SqlSessionFactory開啟資料庫會話

資料庫訪問

二、建立真正與資料庫互動的資料訪問層db,其下建立一個類專門訪問資料庫 例:DBAccess.java

package com.imooc.db;

import java.io.IOException;
import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

  //訪問資料庫類
  public class DBAccess {
      public SqlSession getSqlSession() throws IOException {//丟擲異常在dao層處理
        // 通過配置檔案獲取資料庫連線資訊
        Reader reader = Resources.getResourceAsReader("com/imooc/config/Configuration.xml");
        // 通過配置資訊構建一個SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        // 通過sqlSessionFactory開啟一個資料庫會話
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
      }
  }
複製程式碼

資料互動

三、Dao層與資料互動 例:MessageDao.java

package com.imooc.dao;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.imooc.bean.Message;
import com.imooc.db.DBAccess;

  // 和message表相關的資料庫操作
  public class MessageDao {

    //根據查詢條件查詢訊息列表
    public List<Message> queryMessageList(String command,String description) {
        DBAccess dbAccess = new DBAccess();
        //保證符合泛型
        List<Message> messageList = new ArrayList<Message>();

        SqlSession sqlSession = null;
        try {
            //由於parameterType只接受一個引數,所以講command、description兩個屬性封裝成一個物件
            Message message = new Message();
            message.setCommand(command);
            message.setDescription(description);
            
		    sqlSession = dbAccess.getSqlSession();

       	 	// 通過sqlSession執行SQL語句,查詢一個則是select,多個就是selectList
        	messageList = sqlSession.selectList("Message.queryMessageList", message);
        	} catch (IOException e) {//處理資料訪問層丟擲的異常
            	e.printStackTrace();
        	} finally {
            	if(sqlSession != null) {
                	sqlSession.close();
            	}
        	}
        	return messageList;
    	}

    	//單條刪除
    	public void deleteOne(int id) {
        	DBAccess dbAccess = new DBAccess();
        	SqlSession sqlSession = null;
        	try {
            	sqlSession = dbAccess.getSqlSession();
            	// 通過sqlSession執行SQL語句
            	sqlSession.delete("Message.deleteOne", id);
            	sqlSession.commit();
        	} catch (IOException e) {
            	e.printStackTrace();
        	} finally {
            	if(sqlSession != null) {
                	sqlSession.close();
            	}
        	}
   	 	}

    	//多條刪除
    	public void deleteBatch(List<Integer> ids) {
    		DBAccess dbAccess = new DBAccess();
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = dbAccess.getSqlSession();
    			// 通過sqlSession執行SQL語句
    			sqlSession.delete("Message.deleteBatch", ids);
    			sqlSession.commit();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			if(sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}	
    }
複製程式碼

SQL語句配置檔案

四、在配置層下建立SQL配置層sqlConfig,其中存放dao層下檔案中使用的SQL語句配置檔案 呼叫SQL語句的方法是:mapper標籤的namespace.對應語句標籤(增刪查改)的id

例: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="com.imooc.bean.Message" id="MessageResult">//type:資料庫中欄位對應java中的類
    <id column="ID" jdbcType="INTEGER" property="id"/>//主鍵使用id標籤,否則使用result標籤
    <result column="COMMAND" jdbcType="VARCHAR" property="command"/>
    <result column="DESCRIPTION" jdbcType="VARCHAR" property="description"/>
    <result column="CONTENT" jdbcType="VARCHAR" property="content"/>
  </resultMap>

  //通過parameter接收dao層中傳遞的引數,parameter=包名.型別名

  <select id="queryMessageList" parameterType="String" resultMap="MessageResult">
    select ID,COMMAND,DESCRIPTION,CONTENT from MESSAGE
    //條件檢索
    <where>
    	<if test="command != null and !&quot;&quot;.equals(command.trim())">
	    	and COMMAND=#{command}
	    </if>
	    <if test="description != null and !&quot;&quot;.equals(description.trim())">
	    	and DESCRIPTION like '%' #{description} '%'
	    </if>
    </where>
  </select>

  <delete id="deleteOne" parameterType="int">
  	delete from MESSAGE where ID = #{_parameter}
  </delete>

  <delete id="deleteBatch" parameterType="java.util.List">
  	delete from MESSAGE where ID in(
  		<foreach collection="list" item="item" separator=",">
  			#{item}
  		</foreach>
  	)
  </delete>
</mapper>
複製程式碼

動態SQL拼接

五、動態SQL拼接 使用if、foreach、choose進行動態拼接,mybatis配置檔案中使用ognl(表示式語言),ognl中能直接使用java物件的方法。使用例:

<select id="queryMessageList" parameterType="com.imooc.bean.Message" resultMap="MessageResult">
    select ID,COMMAND,DESCRIPTION,CONTENT from MESSAGE
    <where>
    	<if test="command != null and !&quot;&quot;.equals(command.trim())">
	    	and COMMAND=#{command}
	    </if>
	    <if test="description != null and !&quot;&quot;.equals(description.trim())">
	    	and DESCRIPTION like '%' #{description} '%'
	    </if>
    </where>
  </select>
複製程式碼
<delete id="deleteBatch" parameterType="java.util.List">
  	delete from MESSAGE where ID in(
  		<foreach collection="list" item="item" separator=",">
  			#{item}
  		</foreach>
  	)
  </delete>
複製程式碼

mybatis中的ognl
圖片來源

一對多關係配置

六、一對多關係配置

舉例:

一對多結構

要實現一條指令對應多條內容,資料庫表中需要兩個表,一個為指令表,作為主表,一個為內容表,作為子表。內容表中需要指令id這一指令表主鍵進行關聯。在專案檔案中,建立對應表的實體類,指令表實體類Command中還需要包含子表實體類CommandContent的列表。在xml配置檔案中配置一條能查詢出這個主表的實體類的SQL語句。因為要查詢出主表的實體,sql語句需要寫在主表的xml配置檔案中,將查出的資料填充到主表的屬性中,同時填充子表的列表。配置檔案:

Command.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="Command">
  <resultMap type="com.imooc.bean.Command" id="Command">
    <id column="C_ID" jdbcType="INTEGER" property="id"/>
    <result column="NAME" jdbcType="VARCHAR" property="name"/>
    <result column="DESCRIPTION" jdbcType="VARCHAR" property="description"/>
      <collection property="contentList" resultMap="CommandContent.Content"/>
  </resultMap>
    <!--注意:1、column屬性對應查詢列表的列名,若查詢列表中列名取了別名,那麼對應column也要填寫別名;2、因為字首無效,a.ID和b.ID在查詢出的結果集再去掉字首以後,這兩列的列名是一致的,所以這兩個ID至少有一個要去別名,並且不能與其他列名重複-->

  <select id="queryCommandList" parameterType="com.imooc.bean.Command" resultMap="Command">
    select a.ID C_ID,a.NAME,a.DESCRIPTION,b.ID,b.CONTENT,b.COMMAND_ID 
      from COMMAND a left join COMMAND_CONTENT b on a.ID=b.COMMAND_ID
    <where>
    	<if test="name != null and !&quot;&quot;.equals(name.trim())">
	    	and a.NAME=#{name}
	    </if>
	    <if test="description != null and !&quot;&quot;.equals(description.trim())">
	    	and a.DESCRIPTION like '%' #{description} '%'
	    </if>
    </where>
  </select>
</mapper>
複製程式碼

CommandContent.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="CommandContent">
  <resultMap type="com.imooc.bean.CommandContent" id="Content">
    <id column="ID" jdbcType="INTEGER" property="id"/>
    <result column="CONTENT" jdbcType="VARCHAR" property="content"/>
    <result column="COMMAND_ID" jdbcType="VARCHAR" property="commandId"/>
  </resultMap>
</mapper>
複製程式碼

注意:要在核心配置檔案中引入這兩個xml檔案

然後再在Dao層建立與資料互動的CommandDao.java檔案

package com.imooc.dao;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.imooc.bean.Command;
import com.imooc.db.DBAccess;


public class MessageDao {
    //根據查詢條件查詢指令列表
    public List<Command> queryCommandList(String command,String description) {
        DBAccess dbAccess = new DBAccess();
        List<Command> commandList = new ArrayList<Command>();
        SqlSession sqlSession = null;
        try {
            Command command = new Command();
            command.setName(name);
            command.setDescription(description);
            sqlSession = dbAccess.getSqlSession();
            // 通過sqlSession執行SQL語句,查詢一個則是select,多個就是selectList
            commandList = sqlSession.selectList("Command.queryCommandList", command);
            } catch (IOException e) {//處理資料訪問層丟擲的異常
                e.printStackTrace();
            } finally {
                if(sqlSession != null) {
                    sqlSession.close();
                }
            }
            return commandList;
	}
}
複製程式碼

最後在service中呼叫dao

package com.imooc.service;

import java.util.List;

import com.imooc.bean.Message;
import com.imooc.dao.MessageDao;
import com.imooc.bean.Command;
import com.imooc.dao.CommandDao;
import com.imooc.util.Iconst;

/**
 * 查詢相關的業務功能
 */
public class QueryService {
	public List<Message> queryMessageList(String command,String description) {
		MessageDao messageDao = new MessageDao();
		return messageDao.queryMessageList(command, description);
	}
	
	/**
	 * 通過指令查詢自動回覆的內容
	 * @param command 指令
	 * @return 自動回覆的內容
	 */
	public String queryByCommand(String command) {
		CommandDao commandDao = new CommandDao();
		List<command> commandList;
		if(Iconst.HELP_COMMAND.equals(command)) {
			commandList = commandDao.queryCommandList(null, null);//無條件檢索
			StringBuilder result = new StringBuilder();
			for(int i = 0; i < commandList.size(); i++) {
				if(i != 0) {
					result.append("<br/>");
				}
				result.append("回覆[" + commandList.get(i).getName() + "]可以檢視" + commandList.get(i).getDescription());
			}
			return result.toString();
		}
		commandList = commandDao.queryCommandList(command, null);
		if(commandList.size() > 0) {
            List<CommandContent> contentList = commandList.get(0).getContentList();
            int i = new Random().nextInt(contentList.size());
			return contentList.get(i);
		}
		return Iconst.NO_MATCHING_CONTENT;
	}
}

複製程式碼

其中

package com.imooc.util;

/**
 * 通用的常量定義
 */
public interface Iconst {
	//當指令沒有匹配的自動回覆內容時,用此內容代替。
	public static final String NO_MATCHING_CONTENT = "客官,你沒按套路出牌……我聽不懂你在說什麼哎!";
	public static final String HELP_COMMAND = "幫助";
}
複製程式碼

使用log4j除錯動態SQL

七、使用log4j除錯動態SQL 匯入log4j.jar包,建立log4j.properties配置檔案(放置根目錄下,省去寫載入log4j的方法) log4j配置檔案:

#配置日誌級別和輸出的位置, 級別不小於debug的輸出形式才會輸出,輸出日誌的級別:debug < info < warn < error。mybatis原始碼中日誌輸出使用的是debug,所以此處使用debug
log4j.rootLogger=DEBUG,Console 
log4j.appender.Console=org.apache.log4j.ConsoleAppender
#配置佈局方式
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
#自定義輸出內容的格式
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#為某個特定的包(org.apache)下面去配其他不同的級別
log4j.logger.org.apache=INFO
複製程式碼

自定義輸出內容的格式

%d 產生日誌的時間

%t 產生日誌所處於執行緒的執行緒名稱

%p 輸出的日誌級別

-5輸出的字元至少佔5位字元,不足5位將會用空格補齊

負號指的是補齊的空格在右邊,如果沒有負號,補齊的空格將在左邊

%c 你輸出的日誌所屬於的那個類的全名,包括包名

%m 指的是你輸出的時候附加的資訊將會出現在這個位置

%n 指的是換行

常用標籤

八、常用標籤

sql常用標籤

參考

慕課課程《通過自動回覆機器人學Mybatis---基礎版