2023年6月21日发(作者:)
beetlSql的源码解析beetlsql对外暴露最重要的类是SQLManager,SQLmanager⾥有很多实⽤的⽅法。但是Sqlmnager并不是真正流程的执⾏者,⽽是SQLScript这个类。这个类⾥⾯都是执⾏细节。我们这次只挑出其select⾏为的最终⽅法List select(Class clazz, Map paras, RowMapper mapper)如下所⽰:public List select(Class clazz, Map paras, RowMapper mapper) { //检查是否modele类上是否有带有@Builder的注解,如果有的话,执⾏⼀下before checkAnnotatonBeforeSelect(clazz, paras); //运⾏sql模板,获取实际的sql语句 SQLResult result = run(paras); String sql = l; List objs = ra; ResultSet rs = null; PreparedStatement ps = null; List resultList = null; //执⾏Interceptor的before InterceptorContext ctx = terceptorAsBefore(, sql, false, objs, paras); //如果Interceptor的before有返回值,那么就直接返回,然后执⾏Interceptor的after if (ult() != null) { terceptorAsAfter(ctx, ult()); return (List) ult(); } //再次获取参数,因为有可能被改变 sql = (); objs = as(); Connection conn = null; try { conn = ().getConn(id, false, sql, objs); ps = eStatement(sql); paredStatementPara(ps, objs); rs = eQuery(); //检查是否有RowMapper,如果有⾃定义RowMapper,那么按照Rowmapper进⾏分⾏解析 if (mapper != null) { BeanProcessor beanProcessor = nProcessor(); resultList = new RowMapperResultSetExt(mapper, beanProcessor).handleResultSet(,rs, clazz); } else { //按照正常解析 resultList = mappingSelect(rs, clazz); } //执⾏Interceptor的after terceptorAsAfter(ctx, resultList); //检查是否modele类上是否有带有@Builder的注解,如果有的话,执⾏⼀下after resultList = nnotatonAfterSelect(clazz, resultList, result); //sql 脚本⾥通过listener 实现最后处理,这个⽬前只有等 if (tener() != null) { for (SQLResultListener listener : getListener()) { lectd(resultList,paras,,result); } } return resultList; } catch (SQLException e) { terceptorAsException(ctx, e); throw new BeetlSQLException(_EXCEPTION, e); } finally { clean(false, conn, ps, rs); } }通过这段代码,可以了解到beetlsql的select流程如下:1. 2. 3. query数据库4. 解析statement数据,有Rowmapper按Rowmapper,没有按mappingSelect(rs, clazz);5. 6. 7. Listener那么在⼀般情况下,我们没有新建builder/interceptor/mapper/listener所以只会执⾏第4条的mappingSelect之所以要看这个结构,主要还是对于⼀些⾼级应⽤,要看插⼊⾃定义的⼀些组件的时机。对⼀些组件的解释:builder:官⽅有个@Builder的注解,该注解是针对⾃定义注解的。如果你写⼀个注解,上⾯再盖上@Builder,然后将这个注解放到model类上或者model的属性上就可以被检索到。当然@Builder⾥是有值的,⽐如ObjectSelectBuilder,这是针对查询的接⼝,你还需要新建个⼦类实现它。具体的还是深⼊上⾯代码的第⼀⾏checkAnnotatonBeforeSelect⾥有个()⾥就了解了。interceptor:这是个拦截器,有查询的前置拦截和后置拦截。⽤处我没有仔细看,但可以更改sql语句,⽐如,你可以写个拦截器,思路如下:根据⽅法名,如果带有ByPage的后缀且xx的参数,那么就加上Rowmapper:这个是⾏解析器。注意,是⾏解析器。也就是说,你查询表,查询到了10⾏数据,这个会for循环10⾏,抛出每⼀⾏留给你⾃⼰去⾃定义封装。其实这个有点过度设计了。⼀点⽤没有。作者实际上应该抛出所有数据让⽤户⾃定义封装。listener:⽬前都是⽤于@等orm使⽤了线程的数据传递holder。当然肯定可以后续扩展。
接下来看第4条的mappingSelect⽅法。 @SuppressWarnings("unchecked") public List mappingSelect(ResultSet rs, Class clazz) throws SQLException { List resultList = null; BeanProcessor beanProcessor = nProcessor(); //类型判断需要做性能优化 if (gnableFrom(clazz)) { // 如果是Map的⼦类或者⽗类,返回List
2023年6月21日发(作者:)
beetlSql的源码解析beetlsql对外暴露最重要的类是SQLManager,SQLmanager⾥有很多实⽤的⽅法。但是Sqlmnager并不是真正流程的执⾏者,⽽是SQLScript这个类。这个类⾥⾯都是执⾏细节。我们这次只挑出其select⾏为的最终⽅法List select(Class clazz, Map paras, RowMapper mapper)如下所⽰:public List select(Class clazz, Map paras, RowMapper mapper) { //检查是否modele类上是否有带有@Builder的注解,如果有的话,执⾏⼀下before checkAnnotatonBeforeSelect(clazz, paras); //运⾏sql模板,获取实际的sql语句 SQLResult result = run(paras); String sql = l; List objs = ra; ResultSet rs = null; PreparedStatement ps = null; List resultList = null; //执⾏Interceptor的before InterceptorContext ctx = terceptorAsBefore(, sql, false, objs, paras); //如果Interceptor的before有返回值,那么就直接返回,然后执⾏Interceptor的after if (ult() != null) { terceptorAsAfter(ctx, ult()); return (List) ult(); } //再次获取参数,因为有可能被改变 sql = (); objs = as(); Connection conn = null; try { conn = ().getConn(id, false, sql, objs); ps = eStatement(sql); paredStatementPara(ps, objs); rs = eQuery(); //检查是否有RowMapper,如果有⾃定义RowMapper,那么按照Rowmapper进⾏分⾏解析 if (mapper != null) { BeanProcessor beanProcessor = nProcessor(); resultList = new RowMapperResultSetExt(mapper, beanProcessor).handleResultSet(,rs, clazz); } else { //按照正常解析 resultList = mappingSelect(rs, clazz); } //执⾏Interceptor的after terceptorAsAfter(ctx, resultList); //检查是否modele类上是否有带有@Builder的注解,如果有的话,执⾏⼀下after resultList = nnotatonAfterSelect(clazz, resultList, result); //sql 脚本⾥通过listener 实现最后处理,这个⽬前只有等 if (tener() != null) { for (SQLResultListener listener : getListener()) { lectd(resultList,paras,,result); } } return resultList; } catch (SQLException e) { terceptorAsException(ctx, e); throw new BeetlSQLException(_EXCEPTION, e); } finally { clean(false, conn, ps, rs); } }通过这段代码,可以了解到beetlsql的select流程如下:1. 2. 3. query数据库4. 解析statement数据,有Rowmapper按Rowmapper,没有按mappingSelect(rs, clazz);5. 6. 7. Listener那么在⼀般情况下,我们没有新建builder/interceptor/mapper/listener所以只会执⾏第4条的mappingSelect之所以要看这个结构,主要还是对于⼀些⾼级应⽤,要看插⼊⾃定义的⼀些组件的时机。对⼀些组件的解释:builder:官⽅有个@Builder的注解,该注解是针对⾃定义注解的。如果你写⼀个注解,上⾯再盖上@Builder,然后将这个注解放到model类上或者model的属性上就可以被检索到。当然@Builder⾥是有值的,⽐如ObjectSelectBuilder,这是针对查询的接⼝,你还需要新建个⼦类实现它。具体的还是深⼊上⾯代码的第⼀⾏checkAnnotatonBeforeSelect⾥有个()⾥就了解了。interceptor:这是个拦截器,有查询的前置拦截和后置拦截。⽤处我没有仔细看,但可以更改sql语句,⽐如,你可以写个拦截器,思路如下:根据⽅法名,如果带有ByPage的后缀且xx的参数,那么就加上Rowmapper:这个是⾏解析器。注意,是⾏解析器。也就是说,你查询表,查询到了10⾏数据,这个会for循环10⾏,抛出每⼀⾏留给你⾃⼰去⾃定义封装。其实这个有点过度设计了。⼀点⽤没有。作者实际上应该抛出所有数据让⽤户⾃定义封装。listener:⽬前都是⽤于@等orm使⽤了线程的数据传递holder。当然肯定可以后续扩展。
接下来看第4条的mappingSelect⽅法。 @SuppressWarnings("unchecked") public List mappingSelect(ResultSet rs, Class clazz) throws SQLException { List resultList = null; BeanProcessor beanProcessor = nProcessor(); //类型判断需要做性能优化 if (gnableFrom(clazz)) { // 如果是Map的⼦类或者⽗类,返回List
发布评论