自定义持久层框架MyORMFramework(三)—框架实现

网友投稿 530 2022-10-29

自定义持久层框架MyORMFramework(三)—框架实现

自定义持久层框架MyORMFramework(三)—框架实现

框架端

定义数据源配置和映射语句实体

Configuration

@Data public class Configuration { private DataSource dataSource; /** * key: statementId value:封装好的mappedStatement对象 */ Map mappedStatementMap = new HashMap<>(); }

MappedStatement

@Data public final class MappedStatement { private String id; /** * sql语句 */ private String sql; /** * 参数值类型 */ private Class parameterType; /** * 返回值类型 */ private Class resultType; }

定义配置文件访问的工具类

public class Resources { /** * 根据配置文件的路径,将配置文件加载成字节输入流,存储在内存中 * * @param path * @return */ public static InputStream getResourceAsSteam(String path) throws IOException { InputStream in = Resources.class.getClassLoader().getResourceAsStream(path); if (in == null) { throw new IOException("找不到资源" + path); } return in; } }

定义SqlSessionFactoryBuilder

public class SqlSessionFactoryBuilder { private Configuration configuration; public SqlSessionFactoryBuilder() { this.configuration = new Configuration(); } public SqlSessionFactory build(InputStream inputStream) throws DocumentException, PropertyVetoException, ClassNotFoundException { //1.dom4j解析配置⽂件,封装Configuration XMLConfigerBuilder xmlConfigerBuilder = new XMLConfigerBuilder(configuration); Configuration configuration = xmlConfigerBuilder.parseConfiguration(inputStream); //2.创建SqlSessionFactory对象(工厂类),生产sqlSession:会话对象 SqlSessionFactory sqlSessionFactory = new DefaultSqlSessionFactory(configuration); return sqlSessionFactory; } }

数据源配置和映射语句解析XMLConfigBuilder、XMLMapperBuilder

XMLConfigBuilder

public class XMLConfigerBuilder { private Configuration configuration; public XMLConfigerBuilder() { this.configuration = new Configuration(); } /** * 该方法就是使用dom4j对配置文件进行解析,封装Configuration */ public Configuration parseConfig(InputStream inputStream) throws DocumentException, PropertyVetoException, IOException, ClassNotFoundException { Document document = new SAXReader().read(inputStream); // Element rootElement = document.getRootElement(); List list = rootElement.selectNodes("//property"); Properties properties = new Properties(); for (Element element : list) { String name = element.attributeValue("name"); String value = element.attributeValue("value"); properties.setProperty(name, value); } //连接池 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setDriverClass(properties.getProperty("driverClass")); comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl")); comboPooledDataSource.setUser(properties.getProperty("username")); comboPooledDataSource.setPassword(properties.getProperty("password")); configuration.setDataSource(comboPooledDataSource); //mapper.xml解析: 拿到路径--字节输入流---dom4j进行解析 List mapperList = rootElement.selectNodes("//mapper"); for (Element element : mapperList) { String mapperPath = element.attributeValue("resource"); InputStream resourceAsSteam = Resources.getResourceAsSteam(mapperPath); XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configuration); xmlMapperBuilder.parse(resourceAsSteam); } return configuration; } }

XMLMapperBuilder

public class XMLMapperBuilder { private Configuration configuration; public XMLMapperBuilder(Configuration configuration) { this.configuration = configuration; } public void parse(InputStream inputStream) throws DocumentException, ClassNotFoundException { Document document = new SAXReader().read(inputStream); Element rootElement = document.getRootElement(); String namespace = rootElement.attributeValue("namespace"); List select = rootElement.selectNodes("select"); for (Element element : select) { //id的值 String id = element.attributeValue("id"); String parameterType = element.attributeValue("parameterType"); String resultType = element.attributeValue("resultType"); //输⼊参数class Class parameterTypeClass = getClassType(parameterType); //返回结果class Class resultTypeClass = getClassType(resultType); //statementId String key = namespace + "." + id; //sql语句 String textTrim = element.getTextTrim(); //封装 mappedStatement MappedStatement mappedStatement = new MappedStatement(); mappedStatement.setId(id); mappedStatement.setParameterType(parameterTypeClass); mappedStatement.setResultType(resultTypeClass); mappedStatement.setSql(textTrim); //填充 configuration configuration.getMappedStatementMap().put(key, mappedStatement); } } private Class getClassType (String parameterType) throws ClassNotFoundException { Class aClass = Class.forName(parameterType); return aClass; } }

SqlSessionFactory 接口及DefaultSqlSessionFactory 实现类

SqlSessionFactory

public interface SqlSessionFactory { SqlSession openSession(); }

DefaultSqlSessionFactory

public class DefaultSqlSessionFactory implements SqlSessionFactory { private Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration; } @Override public SqlSession openSession() { return new DefaultSqlSession(configuration); } }

SqlSession 接口及 DefaultSqlSession 实现类

SqlSession

public interface SqlSession { /** * 查询所有 * * @param statementId * @param params * @param * @return * @throws Exception */ List selectList(String statementId, Object... params) throws Exception; /** * 根据条件查询单个 * * @param statementId * @param params * @param * @return * @throws Exception */ T selectOne(String statementId, Object... params) throws Exception; }

DefaultSqlSession

public class DefaultSqlSession implements SqlSession { private Configuration configuration; public DefaultSqlSession(Configuration configuration) { this.configuration = configuration; } @Override public List selectList(String statementid, Object... params) throws Exception { //将要去完成对simpleExecutor里的query方法的调用 SimpleExecutor simpleExecutor = new SimpleExecutor(); MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementid); List list = simpleExecutor.query(configuration, mappedStatement, params); return (List) list; } @Override public T selectOne(String statementid, Object... params) throws Exception { List objects = selectList(statementid, params); if (objects.size() == 1) { return (T) objects.get(0); } else { throw new RuntimeException("查询结果为空或者返回结果过多"); } } }

SQL执行器接口和实现类Executor、SimpleExecutor

Executor

public interface Executor { /** * 执行查询SQL * @param configuration * @param mappedStatement * @param params * @param * @return * @throws Exception */ List query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception; }

SimpleExecutor

/** * SQL执行器实现 * * @author zjq * @date 2022/3/15 */ public class SimpleExecutor implements Executor { @Override public List query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception { // 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 < 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); } // 5. 执行sql ResultSet resultSet = preparedStatement.executeQuery(); //String resultType = mappedStatement.getResultType(); //Class resultTypeClass = getClassType(resultType); Class resultTypeClass = mappedStatement.getResultType(); 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) { //标记处理类:配置标记解析器来完成对占位符的解析处理工作,主要是配合通⽤标记解析器GenericTokenParser类完成对配置⽂件等的解析⼯作,其中TokenHandler主要完成处理 ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler(); //GenericTokenParser :通⽤的标记解析器,完成了代码⽚段中的占位符的解析,然后再根据给定的标记处理器(TokenHandler)来进⾏表达式的处理 //三个参数:分别为openToken (开始标记)、closeToken (结束标记)、handler (标记处理器) GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler); //解析出来的sql String parseSql = genericTokenParser.parse(sql); //#{}里面解析出来的参数名称 List parameterMappings = parameterMappingTokenHandler.getParameterMappings(); BoundSql boundSql = new BoundSql(parseSql, parameterMappings); return boundSql; } }

使用端

创建 sqlMapConfig.xml

创建对应的mapper.xml

UserDao

public interface IUserDao { //查询所有用户 public List findAll() throws Exception; //根据条件进行用户查询 public User findByCondition(User user) throws Exception; }

User实体

@Data public class User { private Long id; private String username; private String password; }

框架查询验证

@Test public void test() throws Exception { InputStream resourceAsSteam = Resources.getResourceAsSteam("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam); SqlSession sqlSession = sqlSessionFactory.openSession(); //调用 User user = new User(); user.setId(1); user.setUsername("张三"); User user2 = sqlSession.selectOne("user.selectOne", user); System.out.println(user2); List users = sqlSession.selectList("user.selectList"); for (User user1 : users) { System.out.println(user1); } }

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot配置Clickhouse的示例代码
下一篇:一个Theano框架用于构建和训练神经网络
相关文章

 发表评论

暂时没有评论,来抢沙发吧~