【MyBatis源碼分析】環境準備
之前一段時間寫了【Spring源碼分析】系列的文章,感覺對Spring的原理及使用各方面都掌握了不少,趁熱打鐵,開始下一個系列的文章【MyBatis源碼分析】,在【MyBatis源碼分析】文章的基礎之上,可以繼續分析數據庫連接池、Spring整合MyBatis源碼、Spring事物管理tx等等。
【MyBatis源碼分析】整個文章結構相較【Spring源碼分析】稍微改一改,後者會在每一部分源碼分析的開頭列出要分析的源碼的實例,比如:
分析Bean流程加載,就會先寫Bean的代碼示例及xml中配置Bean的示例
分析AOP流程,就會先寫AOP的代碼及xml中配置AOP的示例
【MyBatis源碼分析】系列文章,在本文中會一次性地將所有的代碼示例寫完,之後就針對這些代碼一部分一部分進行分析,探究MyBatis原理。
其實MyBatis代碼示例,我在之前的文章裏面記得至少寫了兩遍,完全可以拿之前的文章作為例子,但是這裏要再寫一遍,就希望分享給網友朋友們一點態度:作為一個程序員,還是應當多去寫代碼,多去實踐,不要認為之前寫過的東西就沒必要再寫一遍,之前懂的內容就沒必要再學習一遍,溫故知新,寫得越多用得越熟練,思考得越多成長越快。
SQL準備
首先還是建表,這裏準備一段SQL:
drop table if exists mail; create table mail ( id int auto_increment not null comment ‘主鍵id‘, create_time datetime not null comment ‘創建時間‘, modify_time timestamp not null comment ‘修改時間‘, web_id int not null comment ‘站點id,1表示新浪,2表示QQ,3表示搜狐,4表示火狐‘, mail varchar(50) not null comment ‘郵箱名‘, use_for varchar(30) comment ‘郵箱用途‘, primary key(id), index use_for(use_for), unique index web_id_mail(web_id, mail) )charset=utf8 engine=innodb comment=‘郵箱表‘;
建立實體類
建立完畢SQL之後,第二步一定是為表建立在Java層面的實體類,在SQL層面不同的詞語使用”_”分割,在Java層面不同的詞語則使用駝峰命名法:
對於類名/接口名/枚舉類,使用首字母大寫的駝峰命名法
對於字段,使用首字母小寫的駝峰命名法
現在為mail表建立實體類:
public class Mail {
/** * 主鍵id */ private long id; /** * 創建時間 */ private Date createTime; /** * 修改時間 */ private Date modifyTime; /** * 網站id,1表示新浪,2表示QQ,3表示搜狐,4表示火狐 */ private int webId; /** * 郵箱 */ private String mail; /** * 用途 */ private String useFor; public Mail() { } public Mail(int webId, String mail, String useFor) { this.webId = webId; this.mail = mail; this.useFor = useFor; } public long getId() { return id; } public void setId(long id) { this.id = id; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getModifyTime() { return modifyTime; } public void setModifyTime(Date modifyTime) { this.modifyTime = modifyTime; } public int getWebId() { return webId; } public void setWebId(int webId) { this.webId = webId; } public String getMail() { return mail; } public void setMail(String mail) { this.mail = mail; } public String getUseFor() { return useFor; } public void setUseFor(String useFor) { this.useFor = useFor; } @Override public String toString() { return "MailDO [id=" + id + ", createTime=" + createTime + ", modifyTime=" + modifyTime + ", webId=" + webId + ", mail=" + mail + ", useFor=" + useFor + "]"; }
}
註意實體類一定要重寫toStirng()方法,便於定位問題。
建立數據訪問層
下一步,個人喜好是建立數據訪問層,對於數據訪問層通常有如下約定:
數據訪問層使用Dao命名,它定義了對表的基本增刪改查操作
數據訪問層之上使用Service命名,它的作用是對於數據庫的多操作進行組合,比如先查再刪、先刪再增、先改再查再刪等等,這些操作不會放在Dao層面去操作,而會放在Service層面去進行組合
那麽,首先定義一個MailDao,我定義增刪改查五個方法,其中查詢兩個方法,一個查單個,一個查列表:
public interface MailDao {
/**
* 插入一條郵箱信息
*/
public long insertMail(Mail mail); /** * 刪除一條郵箱信息 */ public int deleteMail(long id); /** * 更新一條郵箱信息 */ public int updateMail(Mail mail); /** * 查詢郵箱列表 */ public List<Mail> selectMailList(); /** * 根據主鍵id查詢一條郵箱信息 */ public Mail selectMailById(long id);
}
接著是Dao的實現類,通常以”Impl”結尾,”Impl”是關鍵字”Implements”的縮寫,表示接口實現類的意思。MailDao的實現類就命名為MailDaoImpl了,代碼為:
public class MailDaoImpl implements MailDao {
private static final String NAME_SPACE = "MailMapper."; private static SqlSessionFactory ssf; private static Reader reader; static { try { reader = Resources.getResourceAsReader("mybatis/config.xml"); ssf = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } } @Override public long insertMail(Mail mail) { SqlSession ss = ssf.openSession(); try { int rows = ss.insert(NAME_SPACE + "insertMail", mail); ss.commit(); if (rows > 0) { return mail.getId(); } return 0; } catch (Exception e) { ss.rollback(); return 0; } finally { ss.close(); } } @Override public int deleteMail(long id) { SqlSession ss = ssf.openSession(); try { int rows = ss.delete(NAME_SPACE + "deleteMail", id); ss.commit(); return rows; } catch (Exception e) { ss.rollback(); return 0; } finally { ss.close(); } } @Override public int updateMail(Mail mail) { SqlSession ss = ssf.openSession(); try { int rows = ss.update(NAME_SPACE + "updateMail", mail); ss.commit(); return rows; } catch (Exception e) { ss.rollback(); return 0; } finally { ss.close(); } } @Override public List<Mail> selectMailList() { SqlSession ss = ssf.openSession(); try { return ss.selectList(NAME_SPACE + "selectMailList"); } finally { ss.close(); } } @Override public Mail selectMailById(long id) { SqlSession ss = ssf.openSession(); try { return ss.selectOne(NAME_SPACE + "selectMailById", id); } finally { ss.close(); } }
}
具體代碼就不看了,會在第二篇文章開始分析。
建立MyBatis配置文件
接著就是建立MyBatis的配置文件了,MyBatis的配置文件有兩個,一個是環境的配置config.xml,一個是具體SQL的編寫mail.xml。首先看一下config.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>
<properties resource="properties/db.properties" /> <settings> <setting name="cacheEnabled" value="true" /> <setting name="lazyLoadingEnabled" value="true"/> <setting name="useGeneratedKeys" value="true"/> </settings> <typeAliases> <typeAlias alias="Mail" type="org.xrq.mybatis.pojo.Mail"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driveClass}"/> <property name="url" value="${url}"/> <property name="username" value="${userName}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mybatis/mail.xml"/> </mappers>
</configuration>
接著是編寫SQL語句的mail.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="MailMapper">
<resultMap type="Mail" id="MailResultMap"> <result column="id" property="id" /> <result column="create_time" property="createTime" /> <result column="modify_time" property="modifyTime" /> <result column="web_id" property="webId" /> <result column="mail" property="mail" /> <result column="use_for" property="useFor" /> </resultMap> <sql id="fields"> id, create_time, modify_time, web_id, mail, use_for </sql> <sql id="fields_value"> null, now(), now(), #{webId}, #{mail}, #{useFor} </sql> <insert id="insertMail" parameterType="Mail" useGeneratedKeys="true" keyProperty="id"> insert into mail( <include refid="fields" /> ) values( <include refid="fields_value" /> ); </insert> <delete id="deleteMail" parameterType="java.lang.Long"> delete from mail where id = #{id}; </delete> <update id="updateMail" parameterType="Mail"> update mail <set> <if test="web_id != 0"> web_id = #{webId} </if> <if test="mail != null"> mail = #{mail} </if> <if test="use_for != null"> use_for = #{useFor} </if> </set> where id = #{id}; </update> <select id="selectMailList" resultMap="MailResultMap"> select <include refid="fields" /> from mail; </select> <select id="selectMailById" resultMap="MailResultMap" parameterType="java.lang.Long"> select <include refid="fields" /> from mail where id = #{id}; </select>
</mapper>
這個mail.xml我盡量寫得全一點,這樣後面分析的時候都會有代碼示例,mail.xml中包括:
●resultMap
●<sql>標簽
●插入主鍵返回主鍵id
●動態sql
建立單元測試代碼
軟件的正確性離不開良好的測試,通常測試有兩種方式:
寫main函數,這種方式我基本不使用,除非是測試一個很小的功能點比如Math.round這種,這種代碼寫完我也會直接刪除的,不會留著提交到代碼庫上
使用單元測試工具比如junit,這是我常用的方式
其實很多公司的JD上面也有寫著”能編寫良好的單元測試代碼”,跑main函數的方式我個人真的是不太推薦。
接著看一下單元測試代碼:
public class TestMyBatis {
private static MailDao mailDao; static { mailDao = new MailDaoImpl(); } @Test public void testInsert() { Mail mail1 = new Mail(1, "[email protected]", "個人使用"); Mail mail2 = new Mail(2, "[email protected]", "企業使用"); Mail mail3 = new Mail(3, "[email protected]", "註冊賬號使用"); System.out.println(mailDao.insertMail(mail1)); System.out.println(mailDao.insertMail(mail2)); System.out.println(mailDao.insertMail(mail3)); } @Test public void testDelete() { System.out.println(mailDao.deleteMail(1)); } @Test public void testUpdate() { Mail mail = new Mail(2, "[email protected]", "個人使用"); mail.setId(2); System.out.println(mailDao.updateMail(mail)); System.out.println(mailDao.selectMailById(2)); } @Test public void testSelectOne() { System.out.println(mailDao.selectMailById(2)); } @Test public void testSelectList() { List<Mail> mailList = mailDao.selectMailList(); if (mailList != null && mailList.size() != 0) { for (Mail mail : mailList) { System.out.println(mail); } } }
}
正確的情況下,應當五個方法跑出來全部是綠色的進度條。
當然,單元測試也可以單獨跑每一個,我個人使用Eclipse/MyEclipse,都是支持的,相信其他IDE肯定也是支持這個功能的。
喜歡小編的可以關註一下哦·~私聊小編也是可以的哦
【MyBatis源碼分析】環境準備