002.持久层框架设计实现及MyBatis源码分析-----自定义持久层框架

一.JDBC问题分析

  1. JDBC使用
/**
     * JDBC连接
     * @param args
     */
    public static void main(String[] args) {
        Connection connection = null ;
        PreparedStatement preparedStatement = null ;
        ResultSet resultSet = null ;

        try {
            //加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            //通过驱动管理类获取数据库连接
            connection = DriverManager.getConnection("dbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8",
                    "root","root");
            //定义Sql语句
            String sql = "SELECT * FROM sys_user";
            //获取预处理statement
            preparedStatement = connection.prepareStatement(sql);
            //向数据库发起请求
            resultSet = preparedStatement.executeQuery();
            //遍历结果集
            while(resultSet.next()) {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                //封装数据
                user.setId(id);
                user.setName(name);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放资源
        }
  1. JDBC存在问题
  1. 数据库创建连接,释放频繁造成资源浪费
  2. sql,配置信息硬编码,代码不易维护
  1. 解决方案
  1. 使用连接池
  2. 使用配置文件
  1. 自定义框架设计
  1. 使用端:
    (1). 提供核心配置
    (2). sqlMapConfig.xml: 存放数据源信息
    (3). mapping.xml: sql语句配置信息
  1. 框架端:
    (1). 读取配置文件
    (2). 解析配置文件
    (3). 创建sqlSessionFactory
    (4). 创建sqlSession接口及实现类,封装CRUD方法

二.自定义框架实现

1. 使用端实现
  1. sqlMapConfig.xml
<configuration>

    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>  <!--驱动-->
    <property name="jdbcUrl" value="jdbc:mysql:///zdy_mybatis"></property>  <!--数据库路径-->
    <property name="user" value="root"></property>  <!--用户-->
    <property name="password" value="root"></property>  <!--密码-->

    <mapper resource="UserMapper.xml"></mapper>

</configuration>
  1. mapping.xml
<mapper namespace="user">

    <!--sql的唯一标识,用namespace.id 区分-->
    <select id="selectList" resultType="com.lgj.user" paramsType="com.lgj.user">
        select * from user where id = #{id}
    </select>
</mapper>
2.框架端
  1. 说明:自定义持久框架本身:本质就是对JDBC代码的封装
  2. 步骤:
  1. 加载配置文件:根据配置文件路径,加载配置文件成字节输入流,存储在内存中
    创建Resources类 方法:InputStream getResourceAsStream(String path)
  1. 创建两个JavaBean: (容器对象):存放的就是配置文件解析出来的内容
    Configuration: 核心配置类 : 存放sqlMapConfig.xml解析出来的内容
    MappedStatement: 映射配置类:存放mapper.xml解析出来内容
  1. 解析配置文件:dom4j
    创建类:SqlSessionFactoryBuilder
    第一:使用dom4j解析配置文件,将解析出来的内容封装到容器对象中
    第二:创建sqlSessionFactory对象;生产sqlSession:会话对象
  1. 创建SqlSessionFacoty接口及实现类DefaultSqlSessionFacory
    第一:openSession() : 生产sqlSession
  1. 创建SqlSession接口及实现类DefaultSession
    定义对数据库的crud操作:
  1. 创建Executor接口及实现类SimpleExecutor实现类
    query : 执行的就是JDBC代码
三.Resources类定义
  1. 定义Resources生成字节流
 /**
     * 获取文件输入流
     * @param path
     * @return
     */
    public static InputStream getResourceAsSteam(String path) {
        InputStream resourcesStream = Resources.class.getResourceAsStream(path);
        return resourcesStream ;
    }
四.容器对象定义
  1. MappedStatement : 存放UserMapping.xml中数据,每一个sql对应一个MappedStatement
public class MappedStatement {
    //id
    private Integer id;
    //sql语句
    private String sql;
    //请求参数
    private String paramterType;
    //返回值
    private String resultType;
    }
  1. Configuration: 存放sqlMapConfig对象
public class Configuration {

    //sqlMapConfig.xml 中数据最终会生产一个DataSource
    private DataSource dataSource ;

    //关联UserMapping.xml中sql key: 为ID
    private Map<String,MappedStatement> mappedStatementMap = new HashMap<String, MappedStatement>();
    }
五.解析配置文件sqlMapConfig.xml中内容
  1. 使用dom4j解析xml内容,封装DataSource
   //1.解析配置文件,封装Configuration
    public void analysis(InputStream in) {
        Document document = new SAXReader().read(inputStream);
        Element rootElement = document.getRootElement();
        List<Element> propertyElements =
                rootElement.selectNodes("//property");
        Properties properties = new Properties();
        for (Element propertyElement : propertyElements) {
            String name = propertyElement.attributeValue("name");
            String value = propertyElement.attributeValue("value");
            properties.setProperty(name,value);
        }
        //连接池
        ComboPooledDataSource comboPooledDataSource = new
                ComboPooledDataSource();
        comboPooledDataSource.setDriverClass(properties.getProperty("driverClass"));
        comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
        comboPooledDataSource.setUser(properties.getProperty("username"));
        comboPooledDataSource.setPassword(properties.getProperty("password"));
        //填充configuration
        configuration.setDataSource(comboPooledDataSource);
    }
六. 解析映射配置文件mapper.xml
  1. mapper.xml部分
		//mapper部分
        List<Element> mapperElements = rootElement.selectNodes("//mapper");
        XMLMapperBuilder xmlMapperBuilder = new
                XMLMapperBuilder(configuration);
        for (Element mapperElement : mapperElements) {
            String mapperPath = mapperElement.attributeValue("resource");
            InputStream resourceAsSteam =
                    Resources.getResourceAsSteam(mapperPath);
            xmlMapperBuilder.parse(resourceAsSteam);
        }
        return configuration;
七.会话对象sqlSession类/方法定义
  1. sqlSession接口及DefaultSqlSession实现类
public interface SqlSession {
	public <E> List<E> selectList(String statementId, Object... param) throws
Exception;
	public <T> T selectOne(String statementId,Object... params) throws
Exception;
	public void close() throws SQLException;
}
  1. DefaultSqlSession
八.查询对象Query定义
  1. 解析#{id} 使用myBatis底层工具类
  2. Query类

你可能感兴趣的:(开源框架源码分析)