当前位置: 首页 > news >正文

自动摘要wordpress山东seo第一

自动摘要wordpress,山东seo第一,学做甜品的网站,科技网站大全1. 手写MyBatis 重要基本原理框架 文章目录 1. 手写MyBatis 重要基本原理框架1.1 第一步#xff1a;IDEA中创建模块1.2 第二步#xff1a;资源工具类#xff0c;方便获取指向配置文件的输入流1.3 第三步#xff1a;定义SqlSessionFactoryBuilder类1.4 第四步#xff1a;分…1. 手写MyBatis 重要基本原理框架 文章目录 1. 手写MyBatis 重要基本原理框架1.1 第一步IDEA中创建模块1.2 第二步资源工具类方便获取指向配置文件的输入流1.3 第三步定义SqlSessionFactoryBuilder类1.4 第四步分析SqlSessionFactory类中有哪些属性1.5 第五步定义JDBCTransaction1.6 第六步事务管理器中需要数据源定义UNPOOLEDDataSource1.7 第七步定义一个MappedStatement 类用于存放 SQL 标签1.8 第八步完善SqlSessionFactory类1.9 第九步完善SqlSessionFactoryBuilder中的build方法1.10 第十步编写SqlSession类中commit rollback close方法1.11 第十一步编写SqlSession类中的insert方法1.12 第十二步编写SqlSession类中的selectOne方法 2. 将我们自己手写的MyBatiks 名为“godbatis”的框架使用Maven打包3. 使用我们自己手写的 MyBatis 名为 “godbatis” 的框架运行测试4. 总结5. 最后 这里我们手写MyBatis 就仅仅只实现 insert() 和 selectOne(单条记录的查询)操作并且有些局限就是数据库的所有字段类型都必须是 varchar 类型才行。 手写框架之前如果没有思路可以先参考一下mybatis的客户端程序通过客户端程序来逆推需要的类参考代码 Test public void testInsert(){SqlSession sqlSession null;try {// 1.创建SqlSessionFactoryBuilder对象SqlSessionFactoryBuilder sqlSessionFactoryBuilder new SqlSessionFactoryBuilder();// 2.创建SqlSessionFactory对象SqlSessionFactory sqlSessionFactory sqlSessionFactoryBuilder.build(Resources.getResourceAsStream(mybatis-config.xml));// 3.创建SqlSession对象sqlSession sqlSessionFactory.openSession();// 4.执行SQLCar car new Car(null, 111, 宝马X7, 70.3, 2010-10-11, 燃油车);int count sqlSession.insert(insertCar,car);System.out.println(更新了几条记录 count);// 5.提交sqlSession.commit();} catch (Exception e) {// 回滚if (sqlSession ! null) {sqlSession.rollback();}e.printStackTrace();} finally {// 6.关闭if (sqlSession ! null) {sqlSession.close();}} }Test public void testSelectOne(){SqlSession sqlSession null;try {// 1.创建SqlSessionFactoryBuilder对象SqlSessionFactoryBuilder sqlSessionFactoryBuilder new SqlSessionFactoryBuilder();// 2.创建SqlSessionFactory对象SqlSessionFactory sqlSessionFactory sqlSessionFactoryBuilder.build(Resources.getResourceAsStream(mybatis-config.xml));// 3.创建SqlSession对象sqlSession sqlSessionFactory.openSession();// 4.执行SQLCar car (Car)sqlSession.selectOne(selectCarByCarNum, 111);System.out.println(car);// 5.提交sqlSession.commit();} catch (Exception e) {// 回滚if (sqlSession ! null) {sqlSession.rollback();}e.printStackTrace();} finally {// 6.关闭if (sqlSession ! null) {sqlSession.close();}} }1.1 第一步IDEA中创建模块 模块godbatis创建普通的Java Maven模块打包方式jar引入相关依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdorg.god.ibatis/groupIdartifactIdgodbatis/artifactIdversion1.0-SNAPSHOT/versionpackagingjar/packagingpropertiesmaven.compiler.source17/maven.compiler.sourcemaven.compiler.target17/maven.compiler.target/propertiesdependencies!-- dom4j 依赖--dependencygroupIdorg.dom4j/groupIdartifactIddom4j/artifactIdversion2.1.3/version/dependency!-- jaxen 依赖--dependencygroupIdjaxen/groupIdartifactIdjaxen/artifactIdversion1.2.0/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.13.2/versionscopetest/scope/dependency!-- mysql驱动依赖--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.30/version/dependencydependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.10/versionscopecompile/scope/dependency/dependencies/project1.2 第二步资源工具类方便获取指向配置文件的输入流 和MyBatis 框架一样这里我们创建一个 Resoures 工具类用来获取配置文件的输入流对象。 工具类的构造方法都是建议私有化的 因为工具类中的方法都是静态的不需要创建对象就能调用 为了避免new对象所有构造方法私有化 这只是一种编程习惯 package org.god.ibatis.utils;import java.io.InputStream;/*** godbatis 框架提供的一个工具类* 这个工具类专门完成“类路径” 中资源的加载*/ public class Resources {/*** 工具类的构造方法都是建议私有化的* 因为工具类中的方法都是静态的不需要创建对象就能调用* 为了避免new对象所有构造方法私有化* 这只是一种编程习惯*/private Resources() {}/*** 从类路径当中加载资源* param resource 放在类路径当中的资源文件* return 指向资源文件的一个输入流*/public static InputStream getResourceAsStream(String resource) {InputStream resourceAsStream ClassLoader.getSystemClassLoader().getResourceAsStream(resource);return resourceAsStream;} } 1.3 第三步定义SqlSessionFactoryBuilder类 提供一个无参数构造方法再提供一个build方法该build方法要返回SqlSessionFactory对象 package org.god.core;import java.io.InputStream;public class SqlSessionFactoryBuilder {/*** 创建构建器对象*/public SqlSessionFactoryBuilder() {}/*** 获取SqlSessionFactory对象* 该方法主要功能是读取godbatis核心配置文件并构建SqlSessionFactory对象* param inputStream 指向核心配置文件的输入流* return SqlSessionFactory对象*/public SqlSessionFactory build(InputStream inputStream){// 解析配置文件创建数据源对象// 解析配置文件创建事务管理器对象// 解析配置文件获取所有的SQL映射对象// 将以上信息封装到SqlSessionFactory对象中// 返回return null;} }1.4 第四步分析SqlSessionFactory类中有哪些属性 事务管理器 GodJDBCTransaction SQL映射对象集合 MapString, GodMappedStatement 1.5 第五步定义JDBCTransaction 事务管理器最好是定义一个接口然后每一个具体的事务管理器都实现这个接口。 package org.god.ibatis.core;import java.sql.Connection;/*** 事务管理接口* 所有的事务管理器都应该遵循该规范* JDBC 事务管理器MANAGED 事务管理器都应该实现这个接口* Transaction事务管理器提供管理事务方法。*/ public interface Transaction {/*** 提交事务*/void commit();/*** 回滚事务*/void rollback();/*** 关闭事务*/void close();/*** 真正的开启数据库连接*/void openConnection();/*** 获取数据库连接对象的*/Connection getConnection();} 关于MyBatis 的事务在 MyBatis 中有两种类型的事务管理器也就是 type“[JDBC|MANAGED]”但是这里我们只实现JDBC这个值的事务。其他另外一个就不实现了。 package org.god.ibatis.core;import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException;/*** JDBC事务管理器godbatis 框架目前只有JdbcTransaction 进行实现*/ public class JdbcTransaction implements Transaction{/*** 数据源属性* 经典的设计面向接口编程*/private DataSource dataSource;/*** 自动提交标志* true 表示自动提交* false 表示不采用自动提交*/private boolean autoCommit;/*** 连接对象*/private Connection connection;public Connection getConnection() {return connection;}public void setConnection(Connection connection) {this.connection connection;}/*** 创建管理器对象* param dataSource* param autoCommit*/public JdbcTransaction(DataSource dataSource, boolean autoCommit) {this.dataSource dataSource;this.autoCommit autoCommit;}Overridepublic void commit() {try {connection.commit();} catch (SQLException e) {e.printStackTrace();}}Overridepublic void rollback() {try {connection.rollback();} catch (SQLException e) {e.printStackTrace();}}Overridepublic void close() {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}public void openConnection() {if (connection null) {try {this.connection dataSource.getConnection();connection.setAutoCommit(autoCommit);} catch (SQLException e) {e.printStackTrace();}}} } package org.god.ibatis.core;import java.sql.Connection;public class ManagedTransaction implements Transaction {Overridepublic void commit() {}Overridepublic void rollback() {}Overridepublic void close() {}Overridepublic void openConnection() {}Overridepublic Connection getConnection() {return null;} } 1.6 第六步事务管理器中需要数据源定义UNPOOLEDDataSource 在MyBatis中有三种内建的数据源类型也就是 type“[UNPOOLED|POOLED|JNDI]”这里我们就实现UNPOOLED 这个值另外两个值就不实现了。 数据源是获取connection对象的 POOlED UNPOOLED JNDI 所有的数据源都要实现 JDK带的规范javax.sql.DataSource package org.god.ibatis.core;import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Logger;/*** 数据源的实现类UNPOOLED* 不使用连接池每一次都新建Connection对象*/ public class UnPooledDataSource implements javax.sql.DataSource {private String driver;private String url;private String username;private String password;/*** 创建一个数据源对象** param driver* param url* param username* param password*/public UnPooledDataSource(String driver, String url, String username, String password) {try {// 直接注册驱动Class.forName(driver);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}this.driver driver;this.url url;this.username username;this.password password;}Overridepublic Connection getConnection() throws SQLException {// 这个连接池godbatis框架可以自己写一个连接池// 从数据库连接池当中获取Connection对象。这个数据库练级吃是我godbatins框架内部封装好的。Connection connection DriverManager.getConnection(url, username, password);return connection;}Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}Overridepublic void setLoginTimeout(int seconds) throws SQLException {}Overridepublic int getLoginTimeout() throws SQLException {return 0;}Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}Overridepublic T T unwrap(ClassT iface) throws SQLException {return null;}Overridepublic boolean isWrapperFor(Class? iface) throws SQLException {return false;} } package org.god.ibatis.core;import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Logger;/*** 数据源的实现类POOlED* 使用godbatis 框架内置的数据库连接池来获取Connection对象。这个不实现*/ public class PooledDataSource implements javax.sql.DataSource{Overridepublic Connection getConnection() throws SQLException {return null;}Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}Overridepublic void setLoginTimeout(int seconds) throws SQLException {}Overridepublic int getLoginTimeout() throws SQLException {return 0;}Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}Overridepublic T T unwrap(ClassT iface) throws SQLException {return null;}Overridepublic boolean isWrapperFor(Class? iface) throws SQLException {return false;} } package org.god.ibatis.core;import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Logger;/*** 数据源的实现类JNDI* 使用godbatis 框架内置的数据库连接池来获取Connection对象。这个不实现*/ public class JNDIDataSource implements javax.sql.DataSource{Overridepublic Connection getConnection() throws SQLException {return null;}Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}Overridepublic void setLoginTimeout(int seconds) throws SQLException {}Overridepublic int getLoginTimeout() throws SQLException {return 0;}Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}Overridepublic T T unwrap(ClassT iface) throws SQLException {return null;}Overridepublic boolean isWrapperFor(Class? iface) throws SQLException {return false;} } 1.7 第七步定义一个MappedStatement 类用于存放 SQL 标签 普通的Java类POJO封装了一个SQL标签一个MappedStatement 对象对应一个SQL标签一个SQL标签中的所有信息封装到MappedStatement对象当中面向对象编程思想 package org.god.ibatis.core;/*** 普通的Java类POJO封装了一个SQL标签* 一个MappedStatement 对象对应一个SQL标签* 一个SQL标签中的所有信息封装到MappedStatement对象当中* 面向对象编程思想*/ public class MappedStatement {/*** sql语句*/private String sql;/*** 要封装的结果集类型有的时候 resultType 是 null* 比如insertdeleteupdate 语句的时候resultType是null* 只有当 sql语句 select 语句的时候 resultType 才有值。*/private String resultType;public MappedStatement(String sql, String resultType) {this.sql sql;this.resultType resultType;}Overridepublic String toString() {return MappedStatement{ sql sql \ , resultType resultType \ };}public String getSql() {return sql;}public void setSql(String sql) {this.sql sql;}public String getResultType() {return resultType;}public void setResultType(String resultType) {this.resultType resultType;} } 1.8 第八步完善SqlSessionFactory类 SqlSessionFactory对象 一个数据库对应一个SqlSessionFactory对象通过SqlSessionFactory对象可以获取SqlSession对象开启会话一个SqlSessionFactory 对象可以开启对哦个SqlSession 会话 在SqlSessionFactory中添加openSession方法 package org.god.ibatis.core;import java.util.List; import java.util.Map;/*** SqlSessionFactory对象* 一个数据库对应一个SqlSessionFactory对象* 通过SqlSessionFactory对象可以获取SqlSession对象开启会话* 一个SqlSessionFactory 对象可以开启对哦个SqlSession 会话*/ public class SqlSessionFactory {/*** 获取Sql会话对象* return*/public SqlSession openSession() {// 开启会话的前提是开启连接transaction.openConnection();// 创建SqlSession 对象SqlSession sqlSession new SqlSession(this);return sqlSession;}public SqlSessionFactory() {}/*** 事务管理属性* 事务管理器可以灵活切换的* SqlSessionFactory类中的事务管理器应该是面向接口编程的* SqlSessionFactory类中的应该有一个事务管理器接口*/private Transaction transaction;/*** 数据源属性*//*** 存放SqL语句的Map集合* key 是 sqlid* value 是对应的 SQL标签信息对象*/private MapString, MappedStatement mappedStatements;public MapString, MappedStatement getMappedStatements() {return mappedStatements;}public void setMappedStatements(MapString, MappedStatement mappedStatements) {this.mappedStatements this.getMappedStatements();}public SqlSessionFactory(Transaction transaction, MapString, MappedStatement mappedStatement) {this.transaction transaction;this.mappedStatements mappedStatement;}public Transaction getTransaction() {return transaction;}public void setTransaction(Transaction transaction) {this.transaction transaction;}} 1.9 第九步完善SqlSessionFactoryBuilder中的build方法 这里我们定义一个常量类用于方便后续的读取提高代码的可读性。 package org.god.ibatis.core;public class Const {public static final String UN_POOLED_DATASOURCE UNPOOLED;public static final String POOLED_DATASOURCE POOLED;public static final String JNDI_DATASOURCE JNDI;public static final String JDBC_TRANSACTION JDBC;public static final String MANAGED_TRANSACTION MANAGED;} package org.god.ibatis.core;import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; import org.god.ibatis.utils.Resources;import javax.sql.DataSource; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;/*** SqlSessionFactory 构建器对象* 通过SqlSessionFactoryBuilder的 build 方法来解析* godbatis-config.xml文件然后创建sqlSessionFactory对象*/public class SqlSessionFactoryBuilder {/****/public SqlSessionFactoryBuilder() {}/*** 解析 godbatis-config.xml 文件来构建sqlSessionFactory对象** param in 指向godbatis-config.xml 文件的一个输入流* return SqlSessionFactory*/public SqlSessionFactory build(InputStream in) {SqlSessionFactory factory null;try {// 解析 godbatis-config.xml 文件SAXReader reader new SAXReader();Document document reader.read(in);Element environments (Element) document.selectSingleNode(/configuration/environments);String defaultId environments.attributeValue(default);Element environment (Element) document.selectSingleNode(/configuration/environments/environment[id defaultId ]);Element transactionElt environment.element(transactionManager);Element dataSourceElt environment.element(dataSource);ListString sqlMapperXMLPathList new ArrayList();ListNode nodes document.selectNodes(//mapper); // 获取整个配置文件中所有的mapper对象nodes.forEach(node - {Element mapper (Element) node;String resource mapper.attributeValue(resource);sqlMapperXMLPathList.add(resource);});// 获取数据源对象DataSource dataSource getDataSource(dataSourceElt);// 获取事务管理器Transaction transaction getTransaction(transactionElt, dataSource);// 获取mappedStatementsMapString, MappedStatement mappedStatements getMappedStatements(sqlMapperXMLPathList);// 解析完成之后构建SqlSessionFactory对象factory new SqlSessionFactory(transaction, mappedStatements);} catch (Exception e) {e.printStackTrace();}return factory;}private MapString, MappedStatement getMappedStatements(ListString sqlMapperXMLPathList) {MapString, MappedStatement mappedStatements new HashMap();sqlMapperXMLPathList.forEach(sqlMapperXMLPath - {try {SAXReader reader new SAXReader();Document document reader.read(Resources.getResourceAsStream(sqlMapperXMLPath));Element mapper (Element) document.selectSingleNode(/mapper);String namespace mapper.attributeValue(namespace);ListElement elements mapper.elements();elements.forEach(element - {String id element.attributeValue(id);// 这里进行了namespace和 id 的拼接生成最终的sqlIdString sqlId namespace . id;String resultType element.attributeValue(resultType);System.out.println(resultType);String sql element.getTextTrim();System.out.println(sql);MappedStatement mappedStatement new MappedStatement(sql, resultType);mappedStatements.put(sqlId,mappedStatement);});} catch (DocumentException e) {e.printStackTrace();}});return mappedStatements;}private Transaction getTransaction(Element transactionElt, DataSource dataSource) {Transaction transaction null;String type transactionElt.attributeValue(type).trim().toUpperCase();if (Const.JDBC_TRANSACTION.equals(type)) {transaction new JdbcTransaction(dataSource, false); // 默认是开启事务的将来需要手动提交的}if (Const.MANAGED_TRANSACTION.equals(type)) {transaction new ManagedTransaction();}return transaction;}/*** 获取数据源对象** param dataSourceElt* return*/private DataSource getDataSource(Element dataSourceElt) {MapString, String map new HashMap();// 获取所有的propertyListElement propertyElts dataSourceElt.elements(property);propertyElts.forEach(propertyElt - {String name propertyElt.attributeValue(name);String value propertyElt.attributeValue(value);map.put(name, value);});DataSource dataSource null;//UNPOOLED POOLED JNDIString type dataSourceElt.attributeValue(type).trim().toUpperCase();if (Const.UN_POOLED_DATASOURCE.equals(type)) {dataSource new UnPooledDataSource(map.get(driver), map.get(url), map.get(username), map.get(password));}if (Const.POOLED_DATASOURCE.equals(type)) {dataSource new PooledDataSource();}if (Const.JNDI_DATASOURCE.equals(type)) {dataSource new JNDIDataSource();}return dataSource;}} 1.10 第十步编写SqlSession类中commit rollback close方法 package org.god.ibatis.core;import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException;public class SqlSession {private SqlSessionFactory factory;public SqlSession(SqlSessionFactory factory) {this.factory factory;}/*** 提交事务*/public void commit() {factory.getTransaction().commit();}/*** 回滚事务*/public void rollback() {factory.getTransaction().rollback();}/*** 关闭事务*/public void close() {factory.getTransaction().close();} } 这里我们手写MyBatis 就仅仅只实现 insert() 和 selectOne(单条记录的查询)操作并且有些局限就是数据库的所有字段类型都必须是 varchar 类型才行。 1.11 第十一步编写SqlSession类中的insert方法 package org.god.ibatis.core;import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException;public class SqlSession {private SqlSessionFactory factory;public SqlSession(SqlSessionFactory factory) {this.factory factory;}/*** 执行insert语句向数据库表当中插入记录** param* return*/public int insert(String sqlId, Object pojo) {int count 0;try {// JDBC代码执行insert 语句 完成插入操作Connection connection factory.getTransaction().getConnection();// insert into t_car values(#{id},#{name},#{age})String godbatisSql factory.getMappedStatements().get(sqlId).getSql();System.out.println(factory.getMappedStatements().get(sqlId));System.out.println(factory.getMappedStatements().get(sqlId).getSql());// insert into t_user values(?,?,?)String sql godbatisSql.replaceAll(#\\{[a-zA-Z0-9_$]*}, ?);PreparedStatement ps connection.prepareStatement(sql);// 给 占位符传值// 难度是什么// 第一: 你不知道有多少个// 第二你不知道该将Pojo对象中的那个属性赋值给哪个// ps.String(第几个问号传什么值) // 这里都是setString所以数据库中的字段类型要求都是varchar才行// 这是godbatis 比较失败的地方int formIndex 0;int index 1;while (true) {int jingIndex godbatisSql.indexOf(#, formIndex);if (jingIndex 0) {break;}System.out.println(index);int youKuoHaoIndex godbatisSql.indexOf(}, formIndex);String propertyName godbatisSql.substring(jingIndex 2, youKuoHaoIndex).trim();System.out.println(propertyName);formIndex youKuoHaoIndex 1;// 有属性名id,怎么获取id 的属性值呢调用 getId()方法String getMethodName get propertyName.toUpperCase().charAt(0) propertyName.substring(1);Method getMethod pojo.getClass().getDeclaredMethod(getMethodName);Object propertyValue getMethod.invoke(pojo);ps.setString(index,propertyValue.toString());index;}count ps.executeUpdate();} catch (Exception e) {e.printStackTrace();}// 给占位符传值return count;}/*** 查询一个对象* param sqlId* param parameterObj* return*/public Object selectOne(String sqlId, Object parameterObj){MappedStatement mappedStatement factory.getMappedStatements().get(sqlId);Connection connection factory.getTransaction().getConnection();// 获取sql语句String godbatisSql mappedStatement.getSql();String sql godbatisSql.replaceAll(#\\{[a-zA-Z0-9_\\$]*}, ?);// 执行sqlPreparedStatement ps null;ResultSet rs null;Object obj null;try {ps connection.prepareStatement(sql);ps.setString(1, parameterObj.toString());rs ps.executeQuery();if (rs.next()) {// 将结果集封装对象通过反射String resultType mappedStatement.getResultType();Class? aClass Class.forName(resultType);obj aClass.newInstance();// 给对象obj属性赋值ResultSetMetaData rsmd rs.getMetaData();int columnCount rsmd.getColumnCount();for (int i 1; i columnCount; i) {String columnName rsmd.getColumnName(i);String setMethodName set columnName.toUpperCase().charAt(0) columnName.substring(1);Method setMethod aClass.getDeclaredMethod(setMethodName, aClass.getDeclaredField(columnName).getType());setMethod.invoke(obj, rs.getString(columnName));}}} catch (Exception e) {throw new RuntimeException(e);} finally {if (rs ! null) {try {rs.close();} catch (SQLException e) {throw new RuntimeException(e);}}try {ps.close();} catch (SQLException e) {throw new RuntimeException(e);}}return obj;}/*** 提交事务*/public void commit() {factory.getTransaction().commit();}/*** 回滚事务*/public void rollback() {factory.getTransaction().rollback();}/*** 关闭事务*/public void close() {factory.getTransaction().close();} } 1.12 第十二步编写SqlSession类中的selectOne方法 package org.god.ibatis.core;import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException;public class SqlSession {private SqlSessionFactory factory;public SqlSession(SqlSessionFactory factory) {this.factory factory;}/*** 执行insert语句向数据库表当中插入记录** param* return*/public int insert(String sqlId, Object pojo) {int count 0;try {// JDBC代码执行insert 语句 完成插入操作Connection connection factory.getTransaction().getConnection();// insert into t_car values(#{id},#{name},#{age})String godbatisSql factory.getMappedStatements().get(sqlId).getSql();System.out.println(factory.getMappedStatements().get(sqlId));System.out.println(factory.getMappedStatements().get(sqlId).getSql());// insert into t_user values(?,?,?)String sql godbatisSql.replaceAll(#\\{[a-zA-Z0-9_$]*}, ?);PreparedStatement ps connection.prepareStatement(sql);// 给 占位符传值// 难度是什么// 第一: 你不知道有多少个// 第二你不知道该将Pojo对象中的那个属性赋值给哪个// ps.String(第几个问号传什么值) // 这里都是setString所以数据库中的字段类型要求都是varchar才行// 这是godbatis 比较失败的地方int formIndex 0;int index 1;while (true) {int jingIndex godbatisSql.indexOf(#, formIndex);if (jingIndex 0) {break;}System.out.println(index);int youKuoHaoIndex godbatisSql.indexOf(}, formIndex);String propertyName godbatisSql.substring(jingIndex 2, youKuoHaoIndex).trim();System.out.println(propertyName);formIndex youKuoHaoIndex 1;// 有属性名id,怎么获取id 的属性值呢调用 getId()方法String getMethodName get propertyName.toUpperCase().charAt(0) propertyName.substring(1);Method getMethod pojo.getClass().getDeclaredMethod(getMethodName);Object propertyValue getMethod.invoke(pojo);ps.setString(index,propertyValue.toString());index;}count ps.executeUpdate();} catch (Exception e) {e.printStackTrace();}// 给占位符传值return count;}/*** 查询一个对象* param sqlId* param parameterObj* return*/public Object selectOne(String sqlId, Object parameterObj){MappedStatement mappedStatement factory.getMappedStatements().get(sqlId);Connection connection factory.getTransaction().getConnection();// 获取sql语句String godbatisSql mappedStatement.getSql();String sql godbatisSql.replaceAll(#\\{[a-zA-Z0-9_\\$]*}, ?);// 执行sqlPreparedStatement ps null;ResultSet rs null;Object obj null;try {ps connection.prepareStatement(sql);ps.setString(1, parameterObj.toString());rs ps.executeQuery();if (rs.next()) {// 将结果集封装对象通过反射String resultType mappedStatement.getResultType();Class? aClass Class.forName(resultType);obj aClass.newInstance();// 给对象obj属性赋值ResultSetMetaData rsmd rs.getMetaData();int columnCount rsmd.getColumnCount();for (int i 1; i columnCount; i) {String columnName rsmd.getColumnName(i);String setMethodName set columnName.toUpperCase().charAt(0) columnName.substring(1);Method setMethod aClass.getDeclaredMethod(setMethodName, aClass.getDeclaredField(columnName).getType());setMethod.invoke(obj, rs.getString(columnName));}}} catch (Exception e) {throw new RuntimeException(e);} finally {if (rs ! null) {try {rs.close();} catch (SQLException e) {throw new RuntimeException(e);}}try {ps.close();} catch (SQLException e) {throw new RuntimeException(e);}}return obj;}/*** 执行查询语句返回一个对象该方法只适合返回一条记录的sql语句* param sqlId* param param* return*/public Object selectOne2(String sqlId,Object param) {Object obj null;try {Connection connection factory.getTransaction().getConnection();MappedStatement mappedStatement factory.getMappedStatements().get(sqlId);// 这是哪个DQL查询语句// select id,name,age from t_user where id #{id}String godbatisSql mappedStatement.getSql();String sql godbatisSql.replaceAll(#\\{[a-zA-Z0-9_$]*}, ?);PreparedStatement ps connection.prepareStatement(sql);// 给占位符传值ps.setString(1,param.toString());// 查询返回的结果集ResultSet rs ps.executeQuery();// 要封装的结果类型String resultType mappedStatement.getResultType();// 从结果集中取数据封装Java对象if(rs.next()) {// 获取 resultType 的 Class对象Class? resultTypeClass Class.forName(resultType);// 调用无参数构造方法创建对象obj resultTypeClass.newInstance(); // Object obj new User();// 给User类的id,name,age 属性赋值// 给Obj 对象的哪个属性赋哪个值/*解决问题的关键将查询结果的列名作为属性名列名是id那么属性就是id列名是name那么属性名就是name*/ResultSetMetaData rsmd rs.getMetaData();int columnCount rsmd.getColumnCount();for (int i 0;i columnCount; i) {String propertyName rsmd.getColumnName(i1);// 拼接方法名:String setMethodName set propertyName.toUpperCase().charAt(0) propertyName.substring(1);// 获取set 方法// Method setMethod resultTypeClass.getDeclaredMethod(setMethodName,resultTypeClass.getDeclaredField(propertyName).getType());Method setMethod resultTypeClass.getDeclaredMethod(setMethodName,String.class);// 调用set 方法给对象Obj属性赋值setMethod.invoke(obj,rs.getString(propertyName));}}} catch (Exception e) {e.printStackTrace();}return obj;}/*** 提交事务*/public void commit() {factory.getTransaction().commit();}/*** 回滚事务*/public void rollback() {factory.getTransaction().rollback();}/*** 关闭事务*/public void close() {factory.getTransaction().close();} } 2. 将我们自己手写的MyBatiks 名为“godbatis”的框架使用Maven打包 根据所提示的放置的路径的位置查看本地仓库中是否已经有jar包 3. 使用我们自己手写的 MyBatis 名为 “godbatis” 的框架运行测试 使用godbatis 就和使用MyBatis是一样的。 第一步准备数据库表t_user。这里我们的手写的MyBatis 框架有所局限缺陷只能识别字段类型为 varchar 的数据所以我们这里的数据表的字段的类型都定义为了 varchar 类型的。 表数据 第二步创建模块普通的Java Maven模块godbatis-test 第三步引入依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.rainbowsea/groupIdartifactIdgodbatis-test/artifactIdversion1.0-SNAPSHOT/versionpackagingjar/packagingpropertiesmaven.compiler.source17/maven.compiler.sourcemaven.compiler.target17/maven.compiler.target/propertiesdependenciesdependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.13.2/versionscopetest/scope/dependencydependencygroupIdorg.god.ibatis/groupIdartifactIdgodbatis/artifactIdversion1.0-SNAPSHOT/version/dependency/dependencies/project第四步编写pojo类 package com.rainbowsea.godbatis.pojo;public class User {private String id;private String name;private String age;public User(String id, String name, String age) {this.id id;this.name name;this.age age;}Overridepublic String toString() {return User{ id id \ , name name \ , age age \ };}public User() {}public String getId() {return id;}public void setId(String id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public String getAge() {return age;}public void setAge(String age) {this.age age;} } 第五步编写核心配置文件godbatis-config.xml ?xml version1.0 encodingUTF-8 ? configurationenvironments defaultmybatisenvironment idmybatis!-- MANAGED 没有用第三框架管理的话都是会被提交的没有事务上的管理了。--transactionManager typeJDBC/ !-- 数据源是获取connection对象的 -- !-- POOlED UNPOOLED JNDI -- !-- 所有的数据源都要实现 JDK带的规范javax.sql.DataSource--dataSource typeUNPOOLEDproperty namedriver valuecom.mysql.cj.jdbc.Driver/property nameurl valuejdbc:mysql://localhost:3306/mybatis/property nameusername valueroot/property namepassword valueMySQL123//dataSource/environment/environmentsmappersmapper resourcesqlMapper.xml/mapper/mappers /configuration第六步编写sql映射文件sqlMapper.xml ?xml version1.0 encodingUTF-8 ?!--namespace 一定要是对应的接口的全限定类名-- mapper namespaceuser!-- id 要是 namespace 对应接口上的方法名: --insert idinsertinsert into t_user values(#{id},#{name},#{age})/insertselect idselectAll resultTypeorg.god.ibatis.pojo.Userselect id,name,age from t_user where id #{id}/select /mapper第七步编写测试类 package com.rainbowsea.godbatis.test;import org.god.ibatis.core.SqlSession; import org.god.ibatis.core.SqlSessionFactory; import org.god.ibatis.core.SqlSessionFactoryBuilder; import org.god.ibatis.pojo.User; import org.god.ibatis.utils.Resources; import org.junit.Test;public class UserMapperTest {Testpublic void testInsertUser() {SqlSessionFactoryBuilder sqlSessionFactoryBuilder new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory sqlSessionFactoryBuilder.build(Resources.getResourceAsStream(godbatis-config.xml));SqlSession sqlSession sqlSessionFactory.openSession();// 执行SQL insertUser user new User(99999, 张三, 20);int count sqlSession.insert(user.insert, user);sqlSession.commit();sqlSession.close();}Testpublic void testSelectOne() {SqlSessionFactoryBuilder sqlSessionFactoryBuilder new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory sqlSessionFactoryBuilder.build(Resources.getResourceAsStream(godbatis-config.xml));SqlSession sqlSession sqlSessionFactory.openSession();// 执行SQL语句Object obj sqlSession.selectOne2(user.selectAll, 666);System.out.println(obj);sqlSession.close();} } 4. 总结 大部分的框架的实现都是反射机制 设计模式 注解 的方式实现的。这里我们手写MyBatis 就仅仅只实现 insert() 和 selectOne(单条记录的查询)操作并且有些局限就是数据库的所有字段类型都必须是 varchar 类型才行。手写MyBatis 让我们更好的了解了 MyBatis 的运行机理是如何通过反射机制读取相关信息进行设置的。 5. 最后 “在这个最后的篇章中我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底继续在其他的领域奋斗。感谢你们我们总会在某个时刻再次相遇。”
http://www.pierceye.com/news/410896/

相关文章:

  • 阜宁网站建设服务商江苏网络公司网站建设
  • 网站语言切换功能如何做wordpress 茶业 主题
  • 南昌企业网站模板建站济南好的seo
  • 食品建设网站公司简介模板免费下载
  • 重庆网站推广运营公司非常酷的wordpress主题
  • 网站未备案被阻断怎么做中国大数据公司排名10强
  • 柳市网站优化茶叶怎么做网站销售
  • 燕郊网站建设公司什么叫动漫设计与制作
  • 瑞安做网站的公司专门做2次元图片的网站
  • 为什么自己做的网站老是404错误个人建设网站流程
  • 柳州网站建设找哪家好沈阳线上教学
  • 外贸网站免费建设做暖暖视频网站大全
  • 做机票在线预订网站手机版传奇发布网站
  • 网站建设 深圳 凡科站内推广
  • 南宁做网站外包公众号二次开发
  • 中国做网站最好的公司郑州网站建设目标
  • 各大网站平台发布信息企业官网模板免费源码
  • 第一次做网站怎么样下手威联通如何做网站
  • 网站有哪几种类型郑州建设信息网可以领证书吗
  • wordpress 百度网盘网站semseo先做哪个
  • 中企动力网站策划小程序开发平台软件
  • 做网站的公司创业泉州网页设计制作
  • 做网站一定要服务器吗做响应式网站
  • 做网站建设涉及哪些算法呼和浩特网站建设电话
  • 网站流量统计 设计做seo需要会网站开发吗
  • 网站前台用什么开发襄阳谷城网站建设
  • 网站icp备案号怎么查北京 网站建设 SEO
  • 西安做网站哪里好wordpress用户前端化
  • 宁波网站优化如何免费加速器
  • 一佰互联自助建站网站公司建设网站价格