内容简介:【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='邮箱表';
很多人可能有不止一个邮箱,新浪的、腾讯的、搜狐的,每个邮箱可能又有不一样的用途,这里就拿邮箱做一个例子。
建立每张表的时候应当注意唯一约束,像这里,一个网站下的邮箱一定是唯一的,不可能在新浪下同时存在两个名为”123@sina.com”的邮箱名,因此对web_id+mail做唯一索引。
建立实体类
建立完毕 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, "123@sina.com", "个人使用"); Mail mail2 = new Mail(2, "123@qq.com", "企业使用"); Mail mail3 = new Mail(3, "123@sohu.com", "注册账号使用"); 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, "123@qq.com", "个人使用"); 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肯定也是支持这个功能的。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Spring 源码学习-环境准备
- Spring 源码学习笔记-环境准备
- linux内核源码之基础准备篇
- 《k8s-1.13版本源码分析》源码准备
- php – Laravel:一般错误:1615准备好的声明需要重新准备
- 详解Openstack环境准备
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。