一、自定义持久层框架

1. JDBC问题分析:

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("jdbc:mysql://localhost:3306/mybatis? characterEncoding=utf-8", "root", "root"); // 定义sql语句?表示占位符 
String sql = "select * from user where username = ?"; // 获取预处理statement 
 preparedStatement = connection.prepareStatement(sql); // 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值 
preparedStatement.setString(1, "tom"); // 向数据库发出sql执行查询,查询出结果集 
resultSet = preparedStatement.executeQuery(); // 遍历查询结果集 
while (resultSet.next()) { 
int id = resultSet.getInt("id"); 
String username = resultSet.getString("username"); // 封装User 
user.setId(id); 
user.setUsername(username); 
} 
System.out.println(user); 
}} catch (Exception e) 
{ e.printStackTrace(); } 
finally { // 释放资源 
if (resultSet != null) { try {resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (preparedStatement != null) { try {preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); }

  1.1 加载驱动获取连接部分代码:

    (1)数据库配置信息存在硬编码 -->配置文件

    (2)频繁创建释放数据库连接-->连接池

  1.2 sql语句部分代码:

    (1).设置参数获取结果集均存在硬编码问题-->配置文件

  1.3 封装返回结果代码:

    手动封装,较为繁琐-->反射,内省

2. 自定义持久层框架设计思路(对以上JDBC问题进行规避)

  2.1 使用端:(项目):

     1.引入2.2的jar包

     2.提供两部分的配置信息:

     (1) 数据库配置信息以及mapper.xml的全路径:sqlMapConfig.xml

       (2)  sql配置信息(sql语句、参数类型、返回值类型):mapper.xml

  2.2 自定义持久层框架本身(工程)本质就是对JDBC代码进行了封装

    (客户端提供sqlMapConfig.xml+mapper.xml)-->Configuration对象(去那个数据库执行,执行什么)-->SqlSessionFactory-->SqlSession-->executer.query()

  (1)  加载配置文件:根据配置文件的路径,加载配置文件成字节输入流,存储在内存中

        创建Resouce类   方法: InputStream getResourceAsStream(String path)

      (2)创建两个类:存放配置文件解析出来的内容

        Configuration:存放sqlMapConfig.xml解析出来的内容

        MappedStatement:存放mapper.xml解析出来的内容

    (3)解析配置文件

class SqlSessionFactoryBuilder {
    SqlSessionFactory builder(InputStream in) {
    /**
    * 使用dom4j解析配置文件,将解析出来的内容封装到容器对象中
    * in-->Configuration
    **/
    /**
    * 创建SqlSessionFactory对象,用来生产会话对象sqlSession
    **/
    SqlSessionFactory ssf = new DefaultSqlSessionFactory();//(4)
    return ssf;
    }
}
public class Configuration {
    //对应于sqlMapConfig.xml
    private DataSource dataSource;
    /**
     * 对应于多个mapper.xml文件
     * key: statementId=namespance+"."+id
     * value:封装好的一条语句信息
     */
    private Map<String,MappedStatement> mappedStatementMap = new HashMap<>();
}

     (4)创建sqlSessionFactory接口及实现类DefaultSqlSessionFactory;

interface SqlSessionFactory{
  SqlSession openSession();
}
class DefaultSqlSessionFactory implements SqlSessionFactory{
  @Override
  SqlSession openSession() {//(5)
    return new DefaultSqlSession();
  }
}

     (5)创建sqlSession接口及实现类DefaultSqlSession:定义对数据库的crud操作

interface SqlSession{
  selectList();
  selectOne();
  update();
  delete();
}
class DefaultSqlSession implements SqlSession{
Configuration configuration;
  @Override
  selectList() {
    return new 
    SimpleExecutor().query(configuration,configuration.mapped***,params);//(6)
  }
}

     (6)创建Executor接口及实现类SimpleExecutor实现类

interface Executor{
  query(Configuration,MappedStatement,Object... params);
}
class SimpleExecutor implements Executor{
  @Override
  query(Configuration,MappedStatement,Object... params) {
    /**
    *  执行的就是JDBC代码,
    *  数据库配置和sql语句分别从Configuration和MappedStatement获取
    *  参数值从params获取
    **/
  }
}

3. 自定义持久层框架问题分析

DaoImpl中:

(1)代码重复(加载配置文件,创建sqlSessionFactory,生产sqlSession)

   (2) statementId存在硬编码问题

解决思路:去掉DaoImpl,使用代理模式生产Dao层接口的代理实现类

UserDao userDao = sqlSession.getMapper(UserDao.class);//userDao得到的是proxy对象
/**
* 代理对象调用接口中任意方法,都会执行invoke方法
**/
List<User> all = userDao.findAll();
/**
*  getMapper的具体实现
*
**/
@Override
    public <T> T getMapper(Class<?> mapperClass) {
        //使用JDK动态代理来为Dao接口生成代理对象,并返回
        final Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //proxy:当前代理对象的引用
        //method:当前被调用方法的引用
        //args:传递的参数
        //底层都还是去执行JDBC代码//来根据不同情况来选择使用selectList和selectOne
                return null;
            }
        });
        return (T) proxyInstance;
    }

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诗酒醉云长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值