点一下关注吧!!!非常感谢!!持续更新!!!
大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html
目前已经更新到了:
框架实现
上节已经实现了部分内容 下面我们继承
SqlSession 相干
SqlSessionFactoryBuilder
- public class SqlSessionFactoryBuilder {
- private Configuration configuration;
- public SqlSessionFactoryBuilder() {
- configuration = new Configuration();
- }
- public SqlSessionFactory build(InputStream inputStream) throws DocumentException, PropertyVetoException, ClassNotFoundException {
- XMLConfigerBuilder xmlConfigerBuilder = new XMLConfigerBuilder(configuration);
- Configuration conf = xmlConfigerBuilder.parseConfiguration(inputStream);
- return new DefaultSqlSessionFactory(conf);
- }
- }
复制代码 SqlSessionFactory
- public interface SqlSessionFactory {
- SqlSession openSession();
- }
复制代码 SqlSession
- public interface SqlSession {
- <E> List<E> selectList(String statementId, Object ...params) throws Exception;
- <T> T selectOne(String statementId, Object ...params) throws Exception;
- void close() throws Exception;
- }
复制代码 DefaultSqlSession
- @AllArgsConstructor
- public class DefaultSqlSession implements SqlSession {
- private Configuration configuration;
- private Executor simpleExecutor = new SimpleExecutor();
- public DefaultSqlSession(Configuration configuration) {
- this.configuration = configuration;
- }
- @Override
- public <E> List<E> selectList(String statementId, Object... params) throws Exception {
- MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
- // System.out.println("DefaultSqlSession => selectList => + " + "statementId: " + statementId + ", mappedStatement: " + mappedStatement);
- return simpleExecutor.query(configuration, mappedStatement, params);
- }
- @Override
- public <T> T selectOne(String statementId, Object... params) throws Exception {
- List<Object> objects = selectList(statementId, params);
- if (objects.size() == 1) {
- return (T) objects.get(0);
- }
- throw new RuntimeException("DefaultSqlSession selectOne 返回结果不唯一: " + statementId);
- }
- @Override
- public void close() throws Exception {
- simpleExecutor.close();
- }
- @Override
- public <T> T getMapper(Class<?> mapperClass) {
- Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- String methodName = method.getName();
- if (method.getDeclaringClass() == Object.class) {
- return method.invoke(this, args);
- }
- String className = method.getDeclaringClass().getName();
- String statementId = className + "." + methodName;
- Type genericReturnType = method.getGenericReturnType();
- if(genericReturnType instanceof ParameterizedType){
- List<Object> objects = selectList(statementId, args);
- return objects;
- }
- return selectOne(statementId,args);
- }
- });
- return (T) proxyInstance;
- }
- }
复制代码
类定义与注解
AllArgsConstructor:
用于生成包罗所有字段的构造方法,简化代码。
表示可以用所有字段直接构造一个 DefaultSqlSession 对象。
DefaultSqlSession:
实现了 SqlSession 接口,作为 MyBatis 的核心会话管理类。
包罗设置 (Configuration) 和执行器 (Executor) 的实例。
属性
- private Configuration configuration:保存设置信息,例如 MappedStatement 映射等,负责管理 SQL 的元数据。
- private Executor simpleExecutor = new SimpleExecutor();默认执行器,用于执行 SQL 语句并返回结果。初始化为 SimpleExecutor 实例。
工作原理总结
查询流程:
- 用户通过 Mapper 接口调用方法。
- 动态署理拦截调用,根据方法署名生成 statementId。
- 调用 selectList 或 selectOne 执行查询。
- 返回查询结果。
核心组件:
- Configuration:管理设置信息。
- MappedStatement:描述 SQL 语句和其映射信息。
- Ezecutor:负责执行 SQL 并返回结果。
- Dynamic Proxy:动态生成 Mapper 接口实现,简化用户调用。
异常处置惩罚:
- 当查询结果不唯一时,selectOne 方法会抛出异常。
- 这种约束确保单条查询返回的结果始终是明确的。
构造方法
DefaultSqlSession(Configuration configuration):
- 担当一个 Configuration 对象并赋值给类中的 configuration 属性。
- 确保该对象的实例在初始化时具备必要的设置信息。
Executor 相干
Executor
- public interface Executor {
- <E> List<E> query(Configuration configuration, MappedStatement mappedStatement, Object[] params) throws Exception;
- void close() throws Exception;
- }
复制代码
DefaultExecutor
- public class SimpleExecutor implements Executor {
- private Connection connection;
- @Override
- public <E> List<E> query(Configuration configuration, MappedStatement mappedStatement, Object[] params) throws Exception {
- connection = configuration.getDataSource().getConnection();
- String sql = mappedStatement.getSql();
- BoundSql boundSql = getBoundSql(sql);
- PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());
- String parameterType = mappedStatement.getParameterType();
- Class<?> parameterTypeClass = getClassType(parameterType);
- List<ParameterMapping> parameterMappingList = boundSql.getParameterMappingList();
- int n = 0;
- for (ParameterMapping pm : parameterMappingList) {
- String content = pm.getName();
- Field declaredField = parameterTypeClass.getDeclaredField(content);
- declaredField.setAccessible(true);
- Object object = declaredField.get(params[0]);
- preparedStatement.setObject(n + 1, object);
- }
- // 执行sql
- ResultSet resultSet = preparedStatement.executeQuery();
- String resultType = mappedStatement.getResultType();
- Class<?> resultTypeClass = getClassType(resultType);
- List<Object> objects = new ArrayList<>();
- // 封装返回结果集
- 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, resultTypeClass.getDeclaredField(columnName).getType().cast(value));
- }
- objects.add(o);
- }
- return (List<E>) objects;
- }
- private BoundSql getBoundSql(String sql) {
- // 标记处理类 配置标记解析器来完成对占位符的解析处理工作
- ParameterMappingTokenHandler parameterMappingHandler = new ParameterMappingTokenHandler();
- GenericTokenParser genericTokenParser = new GenericTokenParser(
- "#{", "}",
- parameterMappingHandler
- );
- // 解析出来的sql
- String parseSql = genericTokenParser.parse(sql);
- // #{} 里边的参数
- List<ParameterMapping> parameterMapping = parameterMappingHandler.getParameterMappings();
- BoundSql boundSql = new BoundSql(parseSql, parameterMapping);
- System.out.println("SimpleExecutor getBoundSql: " + boundSql.getSqlText());
- return boundSql;
- }
- private Class<?> getClassType(String parameterType) throws ClassNotFoundException {
- if(parameterType != null){
- return Class.forName(parameterType);
- }
- return null;
- }
- @Override
- public void close() throws Exception {
- connection.close();
- }
- }
复制代码
类的作用
SimpleExecutor 类的主要作用是:
- 根据传入的 Configuration 和 MappedStatement 来执行 SQL 查询。
- 通过 JDBC 操作数据库,并使用反射将查询结果映射为指定范例的 Java 对象。
- 支持参数绑定和动态 SQL 剖析(如 #{} 占位符的处置惩罚)。
代码逻辑剖析
- 类成员:Connection connection: 用于管理数据库毗连。
核心方法:query
实现 Executor 接口的查询功能,逻辑分为以下几步:
建立数据库毗连:
- connection = configuration.getDataSource().getConnection();
复制代码 获取并剖析 SQL:
- 通过 MappedStatement 获取 SQL 模板(含占位符 #{})。
- 调用 getBoundSql 方法,将 #{} 更换为 ? 并获取参数信息。
创建 PreparedStatement 并绑定参数:
- 根据参数范例信息,通过反射获取参数值。
- 使用 JDBC 的 PreparedStatement 完成 SQL 的参数设置。
执行查询并处置惩罚结果集:
- 通过 ResultSet 获取查询结果。
- 使用反射动态构建结果对象,将结果集中的数据填充到指定的 Java 范例中。
适用场景
该类是 MyBatis 的核心实现之一,适适用来:
- 实现数据库操作的封装。
- 提供动态署理支持的 Mapper 接口。
- 管理 SQL 查询的执行过程。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |