mybatis简单原理介绍

本文简单模拟了mybatis的流程,用demo的形式呈现出来

pom.xml文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.tempus.cn</groupId>
  <artifactId>mybatis</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>mybatis Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    
    <!-- 读取xml文件 -->
    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency>
    
    <!-- MySQL -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.29</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>mybatis</finalName>
  </build>
  <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <java.version>1.8</java.version>
    </properties>
</project>

 

UserMapping.xml

<?xml version="1.0" encoding="UTF-8"?>
<mapper nameSpace="mybatis.mapper.UserMapper">
    <select id="getUserById" resultType ="mybatis.entity.User">
        select * from user where id = ?
    </select>
</mapper>

mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<database>
    <property name="driverClassName">com.mysql.jdbc.Driver</property>
    <property name="url">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8</property>
    <property name="username">root</property>
    <property name="password">123456</property>
</database>

 

UserMapper

package mybatis.mapper;

import mybatis.entity.User;

public interface UserMapper {

    public User getUserById(String id);
}

实体类

User

package mybatis.entity;

import java.io.Serializable;

public class User implements Serializable{

    private static final long serialVersionUID = 1L;
    
    private String id;
    private String username;
    private String password;
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }   
}

工具类

Function

package mybatis.mainfiles;

public class Function {

    private String sqltype;
    private String funcName;
    private String sql;
    private Object resultType;
    private String parameterType;
    public String getSqltype() {
        return sqltype;
    }
    public void setSqltype(String sqltype) {
        this.sqltype = sqltype;
    }
    public String getFuncName() {
        return funcName;
    }
    public void setFuncName(String funcName) {
        this.funcName = funcName;
    }
    public String getSql() {
        return sql;
    }
    public void setSql(String sql) {
        this.sql = sql;
    }
    public Object getResultType() {
        return resultType;
    }
    public void setResultType(Object resultType) {
        this.resultType = resultType;
    }
    public String getParameterType() {
        return parameterType;
    }
    public void setParameterType(String parameterType) {
        this.parameterType = parameterType;
    }  
}

MapperBean

package mybatis.mainfiles;

import java.util.ArrayList;
import java.util.List;

public class MapperBean {

    private String interfaceName;
    private List<Function> list = new ArrayList<>();
    public String getInterfaceName() {
        return interfaceName;
    }
    public void setInterfaceName(String interfaceName) {
        this.interfaceName = interfaceName;
    }
    public List<Function> getList() {
        return list;
    }
    public void setList(List<Function> list) {
        this.list = list;
    }   
}

执行器接口

package mybatis.mainfiles;

public interface Excutor {

    public <T>T query(String statement,Object parameter);
}

 

解析工具类

MyConfiguration

package mybatis.mainfiles;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/*读取与解析配置信息,并返回处理后的Environment*/
public class MyConfiguration {

    private static ClassLoader loader = ClassLoader.getSystemClassLoader();
    //读取xml信息并处理
    public Connection build(String resource){
        
        try {
            InputStream inputStream = loader.getResourceAsStream(resource);
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            Element root = document.getRootElement();
            return evalDataSource(root);
        } catch (Exception e) {
            throw new RuntimeException("error ocurred when eval xml" + resource);
        }
    }
    private Connection evalDataSource(Element node) throws ClassNotFoundException {
        if(!node.getName().equals("database")){
            throw new RuntimeException("root should be <database>");
        }
        String driverClassName = null;
        String url = null;
        String username = null;
        String password = null;
        //获取属性节点
        for(Object item: node.elements("property")){
            Element i = (Element)item;
            String value = getValue(i);
            String name = i.attributeValue("name");
            if(name == null || value == null){
                throw new RuntimeException("<database> should contain name and value");
            }
            switch(name){
                case "url": url = value; break;
                case "username": username = value; break;
                case "password": password = value; break;
                case "driverClassName": driverClassName = value; break;
                default : throw new RuntimeException("<database> property unknow name");
            }            
        }
        Class.forName(driverClassName);
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, username, password);    
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
    
    //获取property属性的值,如果有value的值,则读取,如果没有,则读取内容
    private String getValue(Element node) {
        return node.hasContent() ? node.getText() : node.attributeValue("value");
    }
    
    @SuppressWarnings("rawtypes")
    public MapperBean readMapper(String path){
        MapperBean mapper = new MapperBean();    
        try {
            InputStream inputStream = loader.getResourceAsStream(path);
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            Element root = document.getRootElement();
            
            mapper.setInterfaceName(root.attributeValue("nameSpace").trim());//把mapper节点的nameSpace值存为接口名
            List<Function> list = new ArrayList<>();//用来储存方法的list
            for(Iterator rootIter = root.elementIterator();rootIter.hasNext();){//遍历根节点下面的所有子节点
                Function func = new Function();//用来储存一条方法的信息
                Element e = (Element)rootIter.next();
                String sqltype = e.getName().trim();
                String funcName = e.attributeValue("id").trim();
                String sql = e.getText().trim();
                String resultType = e.attributeValue("resultType").trim();
                func.setFuncName(funcName);
                func.setSqltype(sqltype);
                Object newInstance = null;
                try {
                    newInstance = Class.forName(resultType).newInstance();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
                func.setResultType(newInstance);
                func.setSql(sql);
                list.add(func);
            }
            mapper.setList(list);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return mapper;
    }
}

执行器

package mybatis.mainfiles;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import mybatis.entity.User;

public class MyExcutor implements Excutor {

    private MyConfiguration xmlMyconficuration = new MyConfiguration();

    @Override
    public <T> T query(String sql, Object parameter) {
        Connection connection = getConnection();
        ResultSet set = null;
        PreparedStatement pre = null;
        
        try {
            pre = connection.prepareStatement(sql);
            pre.setString(1, parameter.toString());
            set = pre.executeQuery();            
            User u = new User();
            // 遍历结果集
            while (set.next()) {
                u.setId(set.getString(1));
                u.setPassword(set.getString(2));
                u.setUsername(set.getString(3));
            }
            return (T)u;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (set != null) {
                    set.close();
                }
                if (pre != null) {
                    pre.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private Connection getConnection() {
        try {
            Connection connection = xmlMyconficuration.build("mybatis.xml");
            return connection;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

代理对象

MyMapperProxy

package mybatis.mainfiles;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;

public class MyMapperProxy implements InvocationHandler{

    private MyConfiguration myConfiguration;
    private MySqlSession mySqlSession;
    
    public MyMapperProxy(MyConfiguration myConfiguration, MySqlSession mySqlSession) {
        this.myConfiguration = myConfiguration;
        this.mySqlSession = mySqlSession;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MapperBean readMapper = myConfiguration.readMapper("UserMapping.xml");
        
        //是否是xml对应的接口
        if(!method.getDeclaringClass().getName().equals(readMapper.getInterfaceName())){
            return null;
        }
        List<Function> list = readMapper.getList();
        if(list != null || 0 != list.size()){
            for(Function func: list){
                //id是否和接口方法名一样
                if(method.getName().equals(func.getFuncName())){
                    return mySqlSession.selectOne(func.getSql(), String.valueOf(args[0]));
                }
            }
        }
        return null;
    }

}

MySqlSession

package mybatis.mainfiles;

import java.lang.reflect.Proxy;

public class MySqlSession {

    private Excutor excutor = new MyExcutor();    
    private MyConfiguration myConfiguration = new MyConfiguration();
    
    public <T>T selectOne (String statement,Object parameter){
        return excutor.query(statement, parameter);
    }
    
    @SuppressWarnings("unchecked")
    public <T>T getMapper (Class<T> clas){
        return (T)Proxy.newProxyInstance(clas.getClassLoader(), new Class[]{clas}, new MyMapperProxy(myConfiguration,this));
    }
}

Test

package mybatis.demo;

import mybatis.entity.User;
import mybatis.mainfiles.MySqlSession;
import mybatis.mapper.UserMapper;

public class Test {

    public static void main(String[] args) {  
        MySqlSession sqlsession=new MySqlSession();  
        UserMapper mapper = sqlsession.getMapper(UserMapper.class);  
        User user = mapper.getUserById("1");  
        System.out.println(user.getId() + ":" + user.getUsername());
    } 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值