自定义MyBatis框架,实现一些简单的基础功能
git代码地址:https://gitee.com/lv_guoliang/mybatis
实现思路:
使用端:
提供核心配置文件
sqlMapConfig.xml: 存放数据源信息, 引入mapper.xml
Mapper.xml: sql语句的配置文件信息
框架端:
1. 读取配置文件
读取完以后以流的形式存在,我们不能将读取到的配置信息以流的形式存放在内存中,创建javaBean来存储
(1) Configuration: 存放数据库基本信息、Map<唯一标识, Mapper>: namespace+"."+id
(2)MappedSatement: sql语句、statement类型、输入参数java类型、输出参数java类型
2.解析配置文件
创建SqlSessionFactoryBuilder类:
方法:SqlSessionFactoryBuild():
第一:使用dom4j解析配置文件,将解析出来的内容封装到Configuration和MappedStatement中
第二:创建SqlSessionFactory的实现类DefaultSQLSession
3.创建SqlSessionFactory
方法:openSession(): 获取sqlSession接口的实现类实例对象
4.创建SqlSession接口及实现类:主要封装CRUD方法
核心代码
测试类调用方法
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
ISqlSession sqlSession = sqlSessionFactory.openSession();
userDao = sqlSession.getMapper(IUserDao.class);
User user = new User();
user.setId(4);
user.setUsername("gxy");
user.setPassword("111111");
user.setBirthday("1990-01-01");
int result = userDao.addUser(user);
System.out.println("添加sql成功:" + result);
获取配置文件,构建Configuration对象
public class SqlSessionFactoryBuilder { public SqlSessionFactory build(InputStream in) throws PropertyVetoException, DocumentException { //第一;使用dom4j解析配置文件, 将解析出来的内容封装到Configuration中 XMLConfigBuilder xmlConfigBuilder = new XMLConfigBuilder(); Configuration configuration = xmlConfigBuilder.parseConfig(in); //第二: 创建sql IDefaultSqlSessionFactory defautlSqlSessionFactory = new IDefaultSqlSessionFactory(configuration); return defautlSqlSessionFactory; } }
获取代理对象,生成查询,更新方法
public class DefaultSqlSession implements ISqlSession { private Configuration configuration; public DefaultSqlSession(Configuration configuration) { this.configuration = configuration; } @Override public <T> T getMapper(Class<?> mapperClass) { //使用JDK动态代理来为Dao接口生成代理对象,并返回 Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[] {mapperClass }, new InvocationHandler() { //底层还是去执行JDBC代码 //准备参数1.statementId @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); 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; } else { Class<?> returnType = method.getReturnType(); String type = returnType.getTypeName(); if (type.equals("int")) { return update(statementId, args); } else { Object object = selectOne(statementId, args); return object; } } } }); return (T) proxyInstance; } @Override public <E> List<E> selectList(String statementId, Object... params) throws InvocationTargetException, SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException, IntrospectionException, ClassNotFoundException { //将要去完成对simpleExcutor里的query方法的调用 simpleExecutor simpleExecutor = new simpleExecutor(); MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId); List<Object> queryList = simpleExecutor.query(configuration, mappedStatement, params); return (List<E>) queryList; } @Override public <T> T selectOne(String statementId, Object... params) throws SQLException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException, IntrospectionException, ClassNotFoundException { List<Object> objects = selectList(statementId, params); if (objects.size() == 1) { return (T) objects.get(0); } else { throw new RuntimeException("查询结果为空或者返回结果更多"); } } @Override public int update(String statementId, Object... params) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException { simpleExecutor simpleExecutor = new simpleExecutor(); MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId); return simpleExecutor.update(configuration, mappedStatement, params); } }
具体实现更新,查询方法
public class simpleExecutor implements IExecutor { private PreparedStatement getParamsPreparedStatement(Configuration configuration, MappedStatement mappedStatement, Object... params) throws SQLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException { // 1. 注册驱动,获取链接 Connection connection = configuration.getDataSource().getConnection(); // 2. 获取sql语句 String sql = mappedStatement.getSql(); BoundSql boundSql = getBoundSql(sql); // 3.获取预处理对象 PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText()); // 4. 设置参数 String paramterType = mappedStatement.getParamterType(); Class<?> paramtertypeClass = getClassType(paramterType); List<ParameterMapping> parameterMappingList = boundSql.getParameterMappingList(); for (int i = 0; i < parameterMappingList.size(); i++) { ParameterMapping parameterMapping = parameterMappingList.get(i); String content = parameterMapping.getContent(); //反射 Field declaredField = paramtertypeClass.getDeclaredField(content); //暴力访问 declaredField.setAccessible(true); Object o = declaredField.get(params[0]); preparedStatement.setObject(i + 1, o); } return preparedStatement; } @Override public <E> List<E> query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws SQLException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException, IntrospectionException, ClassNotFoundException { PreparedStatement preparedStatement = this.getParamsPreparedStatement(configuration, mappedStatement, params); // 5. 执行sql ResultSet resultSet = preparedStatement.executeQuery(); String resultType = mappedStatement.getResultType(); Class<?> resultTypeClass = getClassType(resultType); ArrayList<Object> 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<E>) objects; } @Override public int update(Configuration configuration, MappedStatement mappedStatement, Object... params) throws ClassNotFoundException, SQLException, IllegalAccessException, NoSuchFieldException { PreparedStatement preparedStatement = this.getParamsPreparedStatement(configuration, mappedStatement, params); //执行sql int i = preparedStatement.executeUpdate(); return i; } 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<ParameterMapping> parameterMappings = parameterMappingTokenHandler.getParameterMappings(); BoundSql boundSql = new BoundSql(parseSql, parameterMappings); return boundSql; } }
浙公网安备 33010602011771号