【MyBatis源码分析】环境准备

近来有空,鉴于工作经常会使用到mybatis。所以想将这个框架研究的更加彻底一些!

MyBatis源码分析】整个文章结构会在每一部分源码分析的开头列出要分析的源码的实例,比如:

  • 分析加载解析XML配置流程,就会先写相关节点的xml配置及解析的源码展示
  • 分析mybatis四大对象流程,就会先写针对单个对象展示源码

整个系列文章,在本文中会一次性地将所有的代码示例写完,之后就针对这些代码一部分一部分进行分析,探究Mybatis原理。


一、 建表

这里准备一段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='邮箱表';

很多人可能有不止一个邮箱,新浪的、腾讯的、搜狐的,每个邮箱可能又有不一样的用途,这里就拿邮箱做一个例子。

建立每张表的时候应当注意唯一约束,像这里,一个网站下的邮箱一定是唯一的,不可能在新浪下同时存在两个名为"[email protected]"的邮箱名,因此对web_id+mail做唯一索引。


二、 建实体类


在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 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 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();
        }
    }
    
}

 

四、 配置相关环境及SQL的XML文件


MyBatis的配置文件有两个,一个是环境的配置config.xml,一个是具体SQL的编写mail.xml。首先看一下config.xml:






	
	
	
         
         
         
         
		   
		 
		   
		 
		   
		 
		   
		 
		  
		  
		   
		 
		   
		 
		   
		 
		   
		 
		   
		 
		 
		 
		 
		 
     
     
     
     
         
     
     
     
         
             
             
                 
                 
                 
                 
             
         
     
     
     
     
         
     
     
     
 

接着是编写SQL语句的mail.xml:







    
        
        
        
        
        
        
    

    
        id, create_time, modify_time, web_id, mail, use_for
    
    
    
        null, now(), now(), #{webId}, #{mail}, #{useFor}
    

    
        insert into mail(
            
        ) values(
            
        );
    

    
        delete from mail where id = #{id};
    
    
    
        update mail 
        
            
                web_id = #{webId}
            
            
                mail = #{mail}
            
            
                use_for = #{useFor}
            
        
        where id = #{id};
    

    
    
    
    

这个mail.xml我尽量写得全一点,这样后面分析的时候都会有代码示例,mail.xml中包括:

  • resultMap
  • 标签
  • 插入主键返回主键id
  • 动态sql


五、 建立单元测试类


软件的正确性离不开良好的测试,通常测试有两种方式:

  • 写main函数,这种方式我基本不使用,除非是测试一个很小的功能点比如Math.round这种,这种代码写完我也会直接删除的,不会留着提交到代码库上
  • 使用单元测试工具比如junit,这是我常用的方式

接着看一下单元测试代码:

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 mailList = mailDao.selectMailList();
        if (mailList != null && mailList.size() != 0) {
            for (Mail mail : mailList) {
                System.out.println(mail);
            }
        }
    }
    
}

正确的情况下,应当五个方法跑出来全部是绿色的进度条。

当然,单元测试也可以单独跑每一个,Eclipse/MyEclipse/idea都支持的!

现在简单的一个访问数据源的demo就出来,接下来我们就通过这个demo去debug相关mybatis的源码!



 

你可能感兴趣的:(Mybatis源码,Mybatis深度源码分析)