mysql 手写
分使用端与架构端
创建配置文件,数据库连接配置、sqlmapper配置文件
sql语句信息mapper
sqlMapConfig.xml : 存放数据源信息,引入mapper.xml (存放)
Mapper.xml : sql语句的配置文件信息
1.读取配置文件
读取完成以后以流的形式存在,我们不能将读取到的配置信息以流的形式存放在内存中,不好操作,可 以创建javaBean来存储
(1)Configuration : 存放数据库基本信息、Map 唯一标识:namespace + "." + id
(2)MappedStatement:sql语句、statement类型、输入参数java类型、输出 参数java类型
2.解析配置文件
创建sqlSessionFactoryBuilder类: 方法:sqlSessionFactory build(): 第一:使用dom4j解析配置文件,将解析出来的内容封装到Configuration和MappedStatement中 第二:创建SqlSessionFactory的实现类DefaultSqlSession
3.创建SqlSessionFactory: 方法:openSession() : 获取sqlSession接口的实现类实例对象
4.创建sqlSession接口及实现类:主要封装crud方法 方法:selectList(String statementId,Object param):查询所有 selectOne(String statementId,Object param):查询单个 具体实现:封装JDBC完成对数据库表的查询操作
代码步骤
框架层
加载配置文件:根据配置文件路径,加载字节流到内存
创建两个javaBean(容器对象) 存放的是对配置文件解析出来的内容
Configuration:核心配置类,放sqlMapConfig.xml的内容
MappedStatement 映射配置类 放mapper.xml内容
解析配置文件:dom4j
创建SqlSessionFactoryBuilder。方法:build(InputStream in)
一 使用dom4j解析配置文件,装载到容器对象
二 创建SqlSessionFactory对象;生成sqlSession (工厂模式)
DefaultSqlSessionFactory实现SqlSessionFactory
生产sqlSession
创建SqlSession接口及实现类 DefaultSession
定义对数据库的curd操作:selectList() selectOne() update() delete()
创建Executor接口及实现类SimpleExecutor实现类
通用的query(Configuration ,MappedStatement,Object… param) 执行的就是JDBC操作代码
代码执行流程
先加载配置文件
SqlSessionFactoryBuilder通过配置文件流构建SqlSessionFactory对象 得到工厂对象
由工厂对象创建SqlSession
最后由SqlSession提供增删查改方法语句
还提供getMapper方法(代理的dao层实现)
sqlSession底层使用SimpleExecutor提供的query方法,其底层使用jdbc操作数据库代码结构图

核心加载类结构图
代码实现sqlSessionFactoryBuilder.java主要用于创建SqlSessionFactory工厂mysql作用,其中做了两件事:
一 使用dom4j解析配置文件输入流并得到Configuration对象,
二 通过配置对象创建默认工厂类实例DefautSqlSessionFactory用于生产SqlSession的
```java
public class SqlSessionFactoryBuilder {
public SqlSessionFactory build(InputStream in ) throws PropertyVetoException, DocumentException {
// 第一:使用dom4j解析配置文件,将解析出来的内容封装到Configuration中
XMLConfigBuilder xmlConfigBuilder = new XMLConfigBuilder();
Configuration configuration = xmlConfigBuilder.parseConfig(in);
// 第二:创建sqlSessionFactory对象:工厂类:生产sqlSession:会话对象
SqlSessionFactory sqlSessionFactory = new DefautSqlSessionFactory(configuration);
return sqlSessionFactory;
}
} ```
Configuration.java 中主要存储xml解析出来的配置信息,包含数据库链接信息和sql语句信息
```java public class Configuration {
// 数据库连接池
DataSource dataSource;
Map mappedStatementMap = new HashMap();
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public Map getMappedStatementMap() {
return mappedStatementMap;
}
public void setMappedStatementMap(Map mappedStatementMap) {
this.mappedStatementMap = mappedStatementMap;
}
} ```
默认工厂类DefautSqlSessionFactory.java 提供一个openSession()方法,该方法用于获取SqlSession对象
```java public class DefautSqlSessionFactory implements SqlSessionFactory {private Configuration configuration ;
public DefautSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public SqlSession openSession() {
SqlSession sqlSession = new DefaultSqlSession(configuration);
return sqlSession;
}
} ```
持久化核心实现类:DefaultSqlSession.java以上准备工作完成后,由session路由到指定sql语句并执行
```java public class DefaultSqlSession implements SqlSession {
private Configuration configuration;
public DefaultSqlSession(Configuration configuration) {
this.configuration = configuration;
}
public List selectList(String statementid, Object... params) throws Exception {
Executor executor = new SimpleExecutor();
MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementid);
List
} ```
session通过执行器Executor来执行底层查询,SimpleExecutor.java文件如下:
先解析配置文件的sql得到BoundSql对象,boundSql中存储了转成?的sql以及按顺序排列的参数字段名list
通过反射注入参数
```java public class SimpleExecutor implements Executor {
/**
* 使用jdbc进行数据库查询操作
* 1. 获取jdbc的相关对象
* 2. 解析sql语句,用?代替参数#{},同时解析#{}内部参数名并存储
* 3. 根据参数名匹配参数值并设置
* 4. 执行并返回
*
* @param configuration 配置器
* @param mappedStatement mapper配置,sql语句映射等
* @param params 参数
* @param
* @return
* @throws Exception
*/
public List query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception {
// 底层执行器使用jdbc进行数据库查寻操作
// 1. 注册驱动,获取连接
Connection connection = configuration.getDataSource().getConnection();
// 2. 获取sql语句 : select * from user where id = #{id} and username = #{username}
//转换sql语句: select * from user where id = ? and username = ? ,转换的过程中,还需要对#{}里面的值进行解析存储
String sql = mappedStatement.getSql();
BoundSql boundSql = getBoundSql(sql);
// 3.获取预处理对象:preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());
// 4. 设置参数
//获取到了参数的全路径
String paramterType = mappedStatement.getParamterType();
Class<?> paramtertypeClass = getClassType(paramterType);
List parameterMappingList = boundSql.getParameterMappingList();
for (int i = 0; i
preparedStatement.setObject(i+1,o);
}
// 5. 执行sql
ResultSet resultSet = preparedStatement.executeQuery();
String resultType = mappedStatement.getResultType();
Class<?> resultTypeClass = getClassType(resultType);
ArrayList objects = new ArrayList<>();
// 6. 封装返回结果集
while (resultSet.next()){
Object o =resultTypeClass.newInstance();
//元数据
ResultSetMetaData metaData = resultSet.getMetaData();
for (int i = 1; i <= metaData.getColumnCount(); i++) {
// 字段名
String columnName = metaData.getColumnName(i);
// 字段的值
Object value = resultSet.getObject(columnName);
//使用反射或者内省,根据数据库表和实体的对应关系,完成封装
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultTypeClass);
Method writeMethod = propertyDescriptor.getWriteMethod();
writeMethod.invoke(o,value);
}
objects.add(o);
}
return (List) objects;
}
private Class<?> getClassType(String paramterType) throws ClassNotFoundException {
if(paramterType!=null){
Class<?> aClass = Class.forName(paramterType);
return aClass;
}
return null;
}
/**
* 完成对#{}的解析工作:1.将#{}使用?进行代替,2.解析出#{}里面的值进行存储
* @param sql
* @return
*/
private BoundSql getBoundSql(String sql) {
//标记处理类:配置标记解析器来完成对占位符的解析处理工作
ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler);
//解析出来的sql
String parseSql = genericTokenParser.parse(sql);
//#{}里面解析出来的参数名称
List parameterMappings = parameterMappingTokenHandler.getParameterMappings();
BoundSql boundSql = new BoundSql(parseSql,parameterMappings);
return boundSql;
}
} ```
session中每个方法执行的时候还存在代码重复和硬编码问题,为了解决该问题,可以创建getMapper来获取dao层的代理实现对象
定义dao层接口:IUserDao.java,提供两个查询方法
```java public interface IUserDao {List findAll() throws Exception;
User findByCondition(User query) throws Exception;
}
```
```xml
```
```java @Override public T getMapper(Class
(编辑:武汉站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|