MyBatis源码分析(一) —— 实践与使用

最近工作比较忙一点,博客半个月没有更新了。之前一直想要完成一版Mybatis的源码分析。当我看完源码之后,却发现因为懒耽搁了整个过程,现在我们再来重头捋一下,Mybatis是干了什么,怎么干的。首先在本讲,我先介绍一下Mybatis的基础使用。这部分不废话多说,直接拉取的自己的Dem,只为了做一个展示。读者在看这一部分需要给自己一个思考。大家都在使用Mybatis作为数据库连接的一个框架,到底Mybatis做了什么呢?我们都配置了什么?而Mybatis读取我们的配置后是怎么在运行时得到我们想要的结果的呢?

零、传统JDBC的使用:

     此段代码来自:http://blog.csdn.net/lhyzyp/article/details/72868910

     首先,我们看一下JDBC帮我祝我们做了什么。

  1. 加载驱动

  2.连接数据库并获取数据库连接对象

  3.执行sql

  4.返回结果

  5.关闭连接

package com.JDBCdemo;

import java.sql.*;

/**
*
* @author      : pinsily
* @email       : 13160724868@163.com
* @version     : 0.0.1
* @create_time : 2017年6月5日 上午9:31:46
* 
* @update_time : 2017年6月5日 下午16:26:22  增加 增删查改 功能,方便以后使用
*
*/

public class testJDBC {

    /**
     * 加载驱动
     * */
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库连接
     * */
    public static Connection getConnection() {

        String url = "jdbc:mysql://localhost:3306/student";
        String username = "root";
        String password = "pinsily";
        Connection con = null;

        try {
            con = DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return con;
    }


    /**
     * 关闭连接
     * */
    public static void close(ResultSet rs, Statement stm, Connection con) {

        try {

            if (rs != null)
                rs.close();

            if (stm != null) {
                stm.close();
            }

            if (con != null) {
                con.close();
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 插入数据,用得使用可以把 sql语句 当成参数
     * */
    public void insert() {
        String sql = "insert into student_table (name) values('pinsily')";
        Connection con = getConnection();
        Statement stm = null;
        try {

            stm = con.createStatement();

            //执行 SQL 语句并返回结果
            int result = stm.executeUpdate(sql);

            if (result != 0) {
                System.out.println("操作成功,受影响" + result + "行");
            }

        } catch (SQLException e) {
            System.out.println("操作失败");
        } finally {
            close(null, stm, con);
        }
    }

    /**
     * 删除操作,用得使用可以把 sql语句 当成参数
     * */
    public void delete() {

        String sql = "delete from student_table  where name = 'pinsily'";
        Connection con = getConnection();
        Statement stm = null;

        try {

            stm = con.createStatement();    

            int count = stm.executeUpdate(sql);

            System.out.println("删除 " + count + " 条数据\n");

        } catch (SQLException e) {

            System.out.println("删除数据失败");

        }finally {
            close(null, stm, con);
        }

    }

    /**
     * 查询数据库,用得使用可以把 sql语句 当成参数
     * */
    public void query() {

        String sql = "select * from student_table";
        Connection con = getConnection();
        Statement stm = null;
        ResultSet rs = null;

        try {

            stm = con.createStatement();    

            //执行sql查询语句,返回查询数据的结果集
            rs = stm.executeQuery(sql);

            System.out.println("查询结果为:");

            // 判断是否还有下一个数据
            while (rs.next()) { 

                // 根据字段名获取相应的值
                String name = rs.getString("name");
                int id = rs.getInt("id");

                //输出查到的记录的各个字段的值
                System.out.println(id+":"+name);

            }

        } catch (SQLException e) {
            System.out.println("查询数据失败");

        }finally {

            close(rs, stm, con);

        }
    }


    /**
     * 更新操作,用得使用可以把 sql语句 当成参数
     * */
    public void update() {

        String sql = "update student_table set name='zhuyuanpeng' where id = 3 ";
        Connection con = getConnection();
        Statement stm = null;

        try {

            //创建用于执行sql语句的Statement对象
            stm = con.createStatement();                

             // 执行更新操作的sql语句,返回更新数据的个数
            int count = stm.executeUpdate(sql);                    

            //输出更新操作的处理结果
            System.out.println("表中更新 " + count + " 条数据");   


        } catch (SQLException e) {
            System.out.println("更新数据失败");
        }finally {

            close(null, stm, con);

        }
    }


    /**
     * 测试函数
     * */
    public static void main(String[] args) {

        testJDBC j = new testJDBC();

        //j.insert();
        //j.delete();
        //j.update();
        j.query();

    }
}


一、Mybatis的基本使用

 Mybatis其实和基本的JDBC一样,只不过为了我们的使用方便,提供了更多的功能和人性化的配置。

首先让我们看看MyBatis如何QuickStart

 1.1、新建一个mybatis-config.xml文件,对mybatis的基本信息进行配置。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1/lixinjiantest?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

<?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="jdbc.properties"/>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/usermapper.xml"/>
    </mappers>

</configuration>

首先,我们使用了外部的读取配置文件的形式,避免了将url、pwd、uername、driver等信息写死在配置文件中。在我是个新手的时候,我并不能体会到将可配置的文件独立出来的好处。当工作了以后我发现,很多时候将多变的,该独立的,能独立的东西独立出来,可以大大节省您的时间。

其次我们配置了一个池化的数据源

最后我们配置了mapper来描述我们mapper.xml的位置。mapper.xml用来定义sql,和resultMap

<?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="baseDAO.mybatis.mapper.UserMapper">
    <resultMap id="UserResultMap" type="baseDAO.mybatis.domain.User">
        <id column="user_id" property="userId" />
        <result column="user_name" property="userName" />
        <result column="user_phone" property="userPhone" />
        <result column="user_location"  property="userLocation" />

    </resultMap>

    <select id="findAll" resultMap="UserResultMap">
        select user_id,user_phone,user_location,user_name from USER
    </select>
    <select id="findOne" parameterType="Integer" resultMap="UserResultMap">
       select user_id,user_phone,user_location,user_name from USER where user_id=#{id}
    </select>

</mapper>
我们可以清晰的观察到,我们配置了namespace: 这个就是dao层的接口的位置。

resultMap便是你返回的结果和你Java实体类的映射。

再后来我们定义了以Dao层接口方法名同名的SQL语句。每一个Sql语句被定义为一个Statement


再然后,我们只需要定义自定义的DAO层Mapper和我们的实体类,再封装service我们就可以开心的使用Mybatis来完成对数据库的访问了。

package baseDAO.mybatis.mapper;

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

public interface BaseMapper<K,T> {

    public List<T> findAll() throws IOException;

    public List<T> findOne(K k) throws IOException;

}

package baseDAO.mybatis.mapper;

public interface UserMapper extends BaseMapper {

}

package baseDAO.mybatis.domain;

import lombok.Data;

@Data
public class User {
    private Integer userId;
    private Integer userPhone;
    private String  userName;
    private String  userLocation;
}
package baseDAO.mybatis.service;

import baseDAO.mybatis.domain.User;
import baseDAO.mybatis.mapper.UserMapper;
import org.apache.ibatis.session.SqlSession;
import baseDAO.mybatis.utils.SessionHelpUtils;

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

public class UserService {

    public List<User> findAll() throws IOException {
        SqlSession sqlSession = SessionHelpUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.findAll();
    }


    public List<User> findOne(Integer id) throws IOException {
        SqlSession sqlSession = SessionHelpUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return (List<User>) mapper.findOne(id);
    }
}
声明一个Util去获取Mybatis的入口对象:sqlSession

package baseDAO.mybatis.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;

public class SessionHelpUtils {

    private static SqlSessionFactory sqlSessionFactory = null;
    private static SqlSession sqlSession = null;
    static {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        try {
            sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("baseDAO_resources/mybatis-config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession() throws IOException {
        if(sqlSessionFactory != null){
            sqlSession = sqlSessionFactory.openSession();
        }
        return sqlSession;
    }
}
Test/controller

package baseDAO.mybatis.service;

import baseDAO.mybatis.domain.User;
import org.junit.Test;

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

public class UserServiceTest {
    @Test
    public void findAllTest(){
        try {
            new UserService().findAll().stream().forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void findOneTest(){
        UserService userService = new UserService();
        try {
            List<User> one = userService.findOne(1405007);
            System.out.println(one);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}





 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值