Mybatis三步手写

本文详细介绍了如何从零开始手动搭建Mybatis框架,包括引入依赖、配置jdbc、创建xml映射文件、定义实体类、编写测试类、配置相关类和执行器,最后展示了数据库表结构。
摘要由CSDN通过智能技术生成

1、引用依赖
        <!-- 读取xml文件 -->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>

2、代码整体目录

3、jdbc配置和xml

jdbcUrl=jdbc:mysql://127.0.0.1:3306/test1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
driverClass=com.mysql.jdbc.Driver
username=root
password=root

 

<?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="com.sirius.mybatis.mapper.UserMapper">

    <select id="findById" resultMap="com.sirius.mybatis.domain.User">
        select * from user where id = ?
    </select>

</mapper>

4、用户实体类

public class User {
    
    private Long id;
    
    private String username;
    
    private String password;

    public Long getId() {
        return id;
    }

    public void setId(Long 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;
    }
    
}

 

5、测试类

public class MybatisTest {

    
    public static void main(String[] args) {
        SqlSessionFactory sqlSessionFactory = new DefaultSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        System.out.println(sqlSession);
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findById(9L);
        System.out.println(user);
    }
}

6、config相关类

public class Configuration {

    public String jdbcDriver;
    
    private String url;
    
    private String username;
    
    private String password;
    
    private Map<String, MappedStatement> mappedStatements = new HashMap<String, MappedStatement>();

    public String getJdbcDriver() {
        return jdbcDriver;
    }

    public void setJdbcDriver(String jdbcDriver) {
        this.jdbcDriver = jdbcDriver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    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;
    }

    public Map<String, MappedStatement> getMappedStatements() {
        return mappedStatements;
    }

    public void setMappedStatements(Map<String, MappedStatement> mappedStatements) {
        this.mappedStatements = mappedStatements;
    }
    
}

 

public class MapperProxy implements InvocationHandler{

    private SqlSession sqlSession;
    
    public MapperProxy(SqlSession sqlSession) {
        super();
        this.sqlSession = sqlSession;
    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Class<?> returnType = method.getReturnType();
        //判断这个类是不是其子类
        if(Collection.class.isAssignableFrom(returnType)){
            return sqlSession.selectList(method.getDeclaringClass().getName() + "." + method.getName(), args == null ? null : args[0]);
        }else{
            return sqlSession.selectOne(method.getDeclaringClass().getName() + "." + method.getName(), args == null ? null : args[0]);
        }
    }

}

7、执行器

/**
 * 执行器
 * @author EDZ
 */
public interface Executor {

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

 

public class SimpleExecutor implements Executor{

    private Configuration configuration;
    
    public SimpleExecutor(Configuration configuration) {
        super();
        this.configuration = configuration;
    }
    
    public <T> List<T> query(MappedStatement ms, Object parameter) {
        List<T> ret = new ArrayList<T>();
        try {
            Class.forName(configuration.getJdbcDriver());
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        }
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try{
            connection = DriverManager.getConnection(configuration.getUrl(), configuration.getUsername(), configuration.getPassword());
            preparedStatement = connection.prepareStatement(ms.getSql());
            parameterized(preparedStatement, parameter);
            resultSet = preparedStatement.executeQuery();
            handlerResultSet(resultSet,ret, ms.getResultMap());
        }catch(Exception e){
            e.printStackTrace();
        }
        return ret;
    }

    private void parameterized(PreparedStatement preparedStatement,
            Object parameter) throws Exception {
        if(parameter instanceof Integer){
            preparedStatement.setInt(1, (Integer)parameter);
        }else if(parameter instanceof Long){
            preparedStatement.setLong(1, (Long)parameter);
        }else if(parameter instanceof String){
            preparedStatement.setString(1, (String)parameter);
        }
    }
    
    private<T> void handlerResultSet(ResultSet resultSet, List<T> ret, String resultMap){
        Class<T> clazz = null;
        try {
            clazz = (Class<T>)Class.forName(resultMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        try {
            while(resultSet.next()){
                Object entity = clazz.newInstance();
                ReflectionUtil.setProToBeanFromResult(entity, resultSet);
                ret.add((T) entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}

8、MappedStatement

public class MappedStatement {

    private String namespace;
    private String sourceId;
    private String sql;
    private String resultMap;

    public String getNamespace() {
        return namespace;
    }

    public void setNamespace(String namespace) {
        this.namespace = namespace;
    }

    public String getSourceId() {
        return sourceId;
    }

    public void setSourceId(String sourceId) {
        this.sourceId = sourceId;
    }

    public String getSql() {
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }

    public String getResultMap() {
        return resultMap;
    }

    public void setResultMap(String resultMap) {
        this.resultMap = resultMap;
    }

}

9、session相关类

public interface SqlSession {

     <T> T selectOne(String statement, Object parameter);
    
     <T> List<T> selectList(String statement, Object parameter);
    
     <T> T getMapper(Class<T> type);
}

 

public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;
    private Executor executor;

    public DefaultSqlSession(Configuration configuration) {
        super();
        this.configuration = configuration;
        this.executor =  new SimpleExecutor(configuration);
    }

    public <T> T selectOne(String statement, Object parameter) {
        List<T> list = this.<T> selectList(statement, parameter);
        if (list.size() == 1) {
            return list.get(0);
        } else if (list.size() > 1) {
            System.out.println("Expected one result (or null) to be returned by selectOne(), but found: "
                            + list.size());
            return null;
        } else {
            return null;
        }
    }

    public <T> List<T> selectList(String statement, Object parameter) {
        MappedStatement ms = configuration.getMappedStatements().get(statement);
        return executor.query(ms, parameter);
    }

    public <T> T getMapper(Class<T> type) {
        MapperProxy mapperProxy = new MapperProxy(this);
        //动态的实现类
        return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, mapperProxy);
    }

}

 

/**
 * 1、在初始化的时候,加载配置信息 2、生成sqlSession
 *
 * @author EDZ
 *
 */
public interface SqlSessionFactory {
    
    SqlSession openSession();
}

public class DefaultSqlSessionFactory implements SqlSessionFactory {

    private final Configuration configuration = new Configuration();

    public DefaultSqlSessionFactory() {
        //1、载数据库信息
        loadDbInfo();
        //2、加载mapper信息
        loadMapInfo();
    }

    private void loadDbInfo() {
        InputStream inputStream = DefaultSqlSessionFactory.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties properties = new Properties();
        try {
            properties.load(inputStream);
            configuration.setJdbcDriver(properties.getProperty("driverClass"));
            configuration.setUrl(properties.getProperty("jdbcUrl"));
            configuration.setUsername(properties.getProperty("username"));
            configuration.setPassword(properties.getProperty("password"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private void loadMapInfo() {
        URL resources = null;
        resources = DefaultSqlSessionFactory.class.getClassLoader().getResource("mapper");
        File mappers = new File(resources.getFile());
        if(mappers.isDirectory()){
            File[] files = mappers.listFiles();
            for(File file : files){
                loadMapperInfo(file);
            }
        }
        
    }

    private void loadMapperInfo(File file) {
        SAXReader saxReader = new SAXReader();
        Document document = null;
        try {
            document = saxReader.read(file);
            System.out.println(document);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Element node = document.getRootElement();
        String namespace = node.attribute("namespace").getData().toString();
        List<Element> selects = node.elements("select");
        for(Element element: selects){
            MappedStatement mappedStatement = new MappedStatement();
            String id = element.attribute("id").getData().toString();
            mappedStatement.setNamespace(namespace);
            mappedStatement.setSourceId(namespace + "." + id);
            mappedStatement.setResultMap(element.attribute("resultMap").getData().toString());
            mappedStatement.setSql(element.getData().toString());
            configuration.getMappedStatements().put(mappedStatement.getSourceId(), mappedStatement);
        }
    }

    public SqlSession openSession() {
        return new DefaultSqlSession(configuration);
    }
    
    
}


10、其它类

public class ReflectionUtil {

    public static void setProToBeanFromResult(Object entity, ResultSet resultSet) throws SQLException {
        Field[] decfields = entity.getClass().getDeclaredFields();
        for(int i = 0; i < decfields.length; i ++){
            if(decfields[i].getType().getSimpleName().equals("Long")){
                setProToBean(entity, decfields[i].getName(), resultSet.getLong(decfields[i].getName()));
            }else if(decfields[i].getType().getSimpleName().equals("String")){
                setProToBean(entity, decfields[i].getName(), resultSet.getString(decfields[i].getName()));
            }
        }
    }

    private static void setProToBean(Object entity, String name, Object value) {
        Field field = null;
        try {
            field = entity.getClass().getDeclaredField(name);
            field.setAccessible(true);
            field.set(entity, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

11、数据库表

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值