一、自定义持久层框架

论坛 期权论坛 脚本     
已经匿名di用户   2022-4-26 15:50   1344   0

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

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP