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

网站开发用什么电脑好上海快速建站提供商

网站开发用什么电脑好,上海快速建站提供商,旅游网站开发背景意义,西安做网站公司MyBatis插件介绍 MyBatis提供了一种插件(plugin)的功能#xff0c;虽然叫做插件#xff0c;但其实这是拦截器功能。 MyBatis允许使用者在映射语句执行过程中的某一些指定的节点进行拦截调用#xff0c;通过织入拦截器#xff0c;在不同节点修改一些执行过程中的关键属性虽然叫做插件但其实这是拦截器功能。 MyBatis允许使用者在映射语句执行过程中的某一些指定的节点进行拦截调用通过织入拦截器在不同节点修改一些执行过程中的关键属性从而影响SQL的生成、执行和返回结果如来影响Mapper.xml到SQL语句的生成、执行SQL前对预编译的SQL执行参数的修改、SQL执行后返回结果到Mapper接口方法返参POJO对象的类型转换和封装等。 根据上面的对Mybatis拦截器作用的描述可以分析其可能的用途最常见的就是Mybatis自带的分页插件PageHelper或Rowbound参数通过打印实际执行的SQL语句发现我们的分页查询之前先执行了COUNT(*)语句查询数量然后再执行查询时修改了SQL语句即在我们写的SQL语句后拼接上了分页语句LIMIT(offset, pageSize) 此外实际工作中可以使用Mybatis拦截器来做一些数据过滤、数据加密脱敏、SQL执行时间性能监控和告警等既然要准备使用它下面先来了解下其原理 默认情况下MyBatis 允许使用插件来拦截的四种相关操作类方法 Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) ParameterHandler (getParameterObject, setParameters) ResultSetHandler (handleResultSets, handleOutputParameters) StatementHandler (prepare, parameterize, batch, update, query)这几个接口之间的关系大概是这样的 Mybatis整体执行流程 核心对象 Configuration初始化基础配置比如MyBatis的别名等一些重要的类型对象如插件映射器ObjectFactory和typeHandler对象MyBatis所有的配置信息都维持在Configuration对象之中。SqlSessionFactorySqlSession工厂。SqlSession作为MyBatis工作的主要顶层API表示和数据库交互的会话完成必要的数据库增删改查功能。ExecutorMyBatis的内部执行器它负责调用StatementHandler操作数据库并把结果集通过ResultSetHandler进行自动映射另外它还处理二级缓存的操作。StatementHandlerMyBatis直接在数据库执行SQL脚本的对象。另外它也实现了MyBatis的一级缓存。ParameterHandler负责将用户传递的参数转换成JDBC Statement所需要的参数。是MyBatis实现SQL入参设置的对象。ResultSetHandler负责将JDBC返回的ResultSet结果集对象转换成List类型的集合。是MyBatis把ResultSet集合映射成POJO的接口对象。TypeHandler负责Java数据类型和JDBC数据类型之间的映射和转换。MappedStatementMappedStatement维护了一条select|update|delete|insert节点的封装。SqlSource 负责根据用户传递的parameterObject动态地生成SQL语句将信息封装到BoundSql对象中并返回。BoundSql表示动态生成的SQL语句以及相应的参数信息。 MyBatis自定义插件的实现 通过 MyBatis 提供的强大机制使用插件是非常简单的只需实现 Interceptor 接口并指定想要拦截的方法签名即可。 Interceptor 接口的定义如下所示 public interface Interceptor {//拦截器具体实现Object intercept(Invocation invocation) throws Throwable;//拦截器的代理类Object plugin(Object target);//添加属性void setProperties(Properties properties); }相关注解 Intercepts // 描述标志该类是一个拦截器 Signature // 描述指明该拦截器需要拦截哪一个接口的哪一个方法// Signature注解中属性: type; // 四种类型接口中的某一个接口如Executor.class method; // 对应接口中的某一个方法名比如Executor的query方法 args; // 对应接口中的某一个方法的参数比如Executor中query方法因为重载原因有多个args就是指明参数类型从而确定是具体哪一个方法下面来看一个自定义的简单Interceptor示例 import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.*; import org.apache.ibatis.reflection.DefaultReflectorFactory; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import org.springframework.stereotype.Component;import java.lang.reflect.Field; import java.lang.reflect.Method; import java.sql.Connection; import java.util.Properties;Component //拦截StatementHandler类中参数类型为Statement的prepare方法prepare在预编译SQL前加入修改的逻辑 //即拦截 Statement prepare(Connection var1, Integer var2) 方法 Intercepts({Signature(type StatementHandler.class, method prepare, args {Connection.class, Integer.class}) }) Slf4j public class MyPlugin implements Interceptor {Overridepublic Object intercept(Invocation invocation) throws Throwable {// 获取原始sqlStatementHandler statementHandler (StatementHandler) invocation.getTarget();BoundSql boundSql statementHandler.getBoundSql();// 通过MetaObject优雅访问对象的属性这里是访问statementHandler的属性;MetaObject是Mybatis提供的一个用于方便、// 优雅访问对象属性的对象通过它可以简化代码、不需要try/catch各种reflect异常同时它支持对JavaBean、Collection、Map三种类型对象的操作。MetaObject metaObject MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,new DefaultReflectorFactory());// 先拦截到RoutingStatementHandler里面有个StatementHandler类型的delegate变量其实现类是BaseStatementHandler然后就到BaseStatementHandler的成员变量mappedStatementMappedStatement mappedStatement (MappedStatement) metaObject.getValue(delegate.mappedStatement);// 通过反射拦截方法上带有自定义InterceptAnnotation注解的方法并修改sqlString mSql sqlAnnotationEnhance(mappedStatement, boundSql);Field field boundSql.getClass().getDeclaredField(sql);field.setAccessible(true);field.set(boundSql, mSql);return invocation.proceed();}Overridepublic Object plugin(Object target) {if (target instanceof StatementHandler) {return Plugin.wrap(target, this);} else {return target;}}Overridepublic void setProperties(Properties properties) {}/*** 通过反射拦截方法上带有自定义InterceptAnnotation注解的方法并增强sql* param id 方法全路径* param sqlCommandType sql类型* param sql 所执行的sql语句*/private String sqlAnnotationEnhance(MappedStatement mappedStatement, BoundSql boundSql) throws ClassNotFoundException {// 获取到原始sql语句String sql boundSql.getSql().toLowerCase();// sql语句类型 select、delete、insert、updateString sqlCommandType mappedStatement.getSqlCommandType().toString();// 数据库连接信息// Configuration configuration mappedStatement.getConfiguration();// ComboPooledDataSource dataSource (ComboPooledDataSource)configuration.getEnvironment().getDataSource();// dataSource.getJdbcUrl();// id为执行的mapper方法的全路径名如com.cq.UserMapper.insertUser 便于后续使用反射String id mappedStatement.getId();// 获取当前所拦截的方法名称String mName id.substring(id.lastIndexOf(.) 1);// 通过类全路径获取Class对象Class? classType Class.forName(id.substring(0, id.lastIndexOf(.)));// 获得参数集合String paramString null;if (boundSql.getParameterObject() ! null) {paramString boundSql.getParameterObject().toString();}// 遍历类中所有方法名称并匹配上当前所拦截的方法for (Method method : classType.getDeclaredMethods()) {if (mName.equals(method.getName())) {// 判断方法上是否带有自定义InterceptAnnotation注解InterceptAnnotation interceptorAnnotation method.getAnnotation(InterceptAnnotation.class);if (interceptorAnnotation ! null interceptorAnnotation.flag()) {log.info(intercept func:{}, type:{}, origin SQL{}, mName, sqlCommandType, sql);// 场景1分页功能 return sql limit 1;if (select.equals(sqlCommandType.toLowerCase())) {if (!sql.toLowerCase().contains(limit)) {sql sql limit 1;}}// 场景2校验功能 :update/delete必须要有where条件并且打印出where中的条件if (update.equals((sqlCommandType.toLowerCase())) || delete.equals(sqlCommandType.toLowerCase())) {if (!sql.toLowerCase().contains(where)) {log.warn(update or delete not safe!);}}// 场景3分库分表: 根据userId哈希,替换注解中的表名if (sql.toLowerCase().contains(interceptorAnnotation.value())) {String userId getValue(paramString, userId);if (userId ! null) {int num Integer.parseInt(userId);// 模拟分10个库5个表String data_source_id String.valueOf(num % 10);String new_table interceptorAnnotation.value().concat(_).concat(String.valueOf(num % 5));log.info(set data_source_id:{}, table: {}, data_source_id, new_table);// 设置data_source_id路由 替换sql表名sql StringUtils.replace(sql, interceptorAnnotation.value(), new_table);}}log.info(new SQL{}, sql);return sql;}}}return sql;}String getValue(String param, String key) {if (param null) {return null;}String[] keyValuePairs param.substring(1, param.length() - 1).split(,);for (String pair : keyValuePairs) {String[] entry pair.split();if (entry[0].trim().equals(key)) {return entry[1].trim();}}return null;} }自定义注解如下 import java.lang.annotation.*;Target({ElementType.METHOD, ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented public interface InterceptAnnotation {String value() default ;/*** true增强、false忽略*/boolean flag() default true; }添加插件 Component public class DynamicPluginHelper {Autowiredprivate ListSqlSessionFactory sqlSessionFactoryList;Autowiredprivate MyPlugin myPlugin;PostConstructpublic void addMysqlInterceptor() {for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {org.apache.ibatis.session.Configuration configuration sqlSessionFactory.getConfiguration();configuration.addInterceptor(myPlugin);}} } 测试结果如下 sql.MyPlugin : intercept func:findUser, type:SELECT, origin SQLselect * from t_user where id ? sql.MyPlugin : set data_source_id:4, table: t_user_4 sql.MyPlugin : new SQLselect * from t_user_4 where id ? limit 1问题记录 错误描述 There is no getter for property named delegate in class com.sun.proxy.$Proxy32 错误原因 1、你有多个拦截器拦截同一对象的同一行为。测试时避免其他拦截器的干扰可以先把注册的拦截器注释掉。 2、依赖包版本不对 3、拦截器配置类放置的位置不正确导致包没找到 参考 https://blog.csdn.net/minghao0508/article/details/124420953 https://blog.csdn.net/qq_36881887/article/details/111589294 https://www.cnblogs.com/simplejavahome/p/16617112.html https://www.cnblogs.com/nefure/p/16948633.html https://blog.csdn.net/u011602668/article/details/128735771
http://www.w-s-a.com/news/322046/

相关文章:

  • 网站内容优化方法深圳市宝安区怎么样
  • 视频网站开发视频公司网站制作多少钱
  • 单页简洁手机网站模板购物软件
  • 素材网站官网低价网站建设费用预算
  • 苏州网站设计kgwl个人网站有什么外国广告做
  • 浙江省网站建设报价简单网站开发工具
  • 物流网站的建设wordpress电视直播插件下载
  • 简述网站开发流程青岛做网站建设价格低
  • 网站开发的业务需求分析杭州推广公司
  • 网站建设技术实现难点app开发需要哪些软件
  • 响水建设局网站做网站需要会哪些知识
  • 企业制作企业网站个人网站可以做百度竞价
  • 做网站找投资人wordpress 5 主题教程
  • 做国外网站汇款用途是什么wordpress图片主题晨曦
  • 网站设计跟网站开发区别为什么网站需要维护
  • m 的手机网站怎么做网络推广方式和方法
  • wordpress图片自动轮播插件seo门户网站建设
  • 制作商业网站传奇网页游戏排名
  • 网站免费推广方案长沙房地产网站设计
  • 济南网站建设cnwenhui中交路桥建设网站
  • 韶关网站开发网站建设任务分解
  • 网站建设核心点阿根廷网站后缀
  • 哪些网站可以做招商广告语学校官网页面设计
  • 十堰城市建设网站网站开发流程宜春
  • 内江网站建设郑州网站优化外包
  • 土地流转网站建设项目云南抖音推广
  • 建设银行网站无法打开2021年有没有人给个网站
  • 高端手机网站建设网站建设岗位绩效
  • 泰安网络推广 网站建设 网站优化免费素材网站psd
  • 做企业网站联系网站开发具体的工作内容