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

企业网站建设的流程/seo图片优化的方法

企业网站建设的流程,seo图片优化的方法,网站做充值和提现,做各企业网站大概多少钱本文提供了一种自动生成sql语句的方法,它针对的对象是有主键或唯一索引的单表,提供的操作有增、删、改、查4种。理解本文和本文的提供的代码需要有java注解的知识,因为本文是基于注解生成sql的。本文适配的mybatis版本是3.2.2。 准备 为什么在…

本文提供了一种自动生成sql语句的方法,它针对的对象是有主键或唯一索引的单表,提供的操作有增、删、改、查4种。理解本文和本文的提供的代码需要有java注解的知识,因为本文是基于注解生成sql的。本文适配的mybatis版本是3.2.2

准备

为什么在StatementHandler拦截

深入浅出MyBatis-Sqlsession章节介绍了一次sqlsession的完整执行过程,从中可以知道sql的解析是在StatementHandler里完成的,所以为了自动生成sql需要拦截StatementHandler

MetaObject简介

在我的实现里大量使用了MetaObject这个对象,因此有必要先介绍下它。MetaObjectMybatis提供的一个的工具类,通过它包装一个对象后可以获取或设置该对象的原本不可访问的属性(比如那些私有属性)。它有个三个重要方法经常用到:

1)       MetaObject forObject(Object object,ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory)

2)       Object getValue(String name)

3)       void setValue(String name, Object value)

方法1)用于包装对象;方法2)用于获取属性的值(支持OGNL的方法);方法3)用于设置属性的值(支持OGNL的方法);

插件的原理

参见深入浅出Mybatis-插件原理

 

有了上面这些基础知识的准备后,就可以我们的主题了。

拦截器签名

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})
public class AutoMapperInterceptor implements Interceptor {
...
}

从签名里可以看出,要拦截的目标类型是StatementHandler(注意:type只能配置成接口类型),拦截的方法是名称为prepare参数为Connection类型的方法。

intercept的实现

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})
public class AutoMapperInterceptor implements Interceptor {private static final Log logger = LogFactory.getLog(AutoMapperInterceptor.class);private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler = (StatementHandler) invocation.getTarget();MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY,DEFAULT_OBJECT_WRAPPER_FACTORY);// 分离代理对象链while (metaStatementHandler.hasGetter("h")) {Object object = metaStatementHandler.getValue("h");metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);}// 分离最后一个代理对象的目标类while (metaStatementHandler.hasGetter("target")) {Object object = metaStatementHandler.getValue("target");metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);}String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration");Object parameterObject = metaStatementHandler.getValue("delegate.boundSql.parameterObject");if (null == originalSql || "".equals(originalSql)) {String newSql = "";MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");// 根据ID生成相应类型的sql语句(id需剔除namespace信息)String id = mappedStatement.getId();id = id.substring(id.lastIndexOf(".") + 1);if ("insert".equals(id)) {newSql = SqlBuilder.buildInsertSql(parameterObject);} else if ("update".equals(id)) {newSql = SqlBuilder.buildUpdateSql(parameterObject);} else if ("delete".equals(id)) {newSql = SqlBuilder.buildDeleteSql(parameterObject);} else if ("select".equals(id)) {newSql = SqlBuilder.buildSelectSql(parameterObject);}logger.debug("Auto generated sql:" + newSql);//SqlSource sqlSource = buildSqlSource(configuration, newSql, parameterObject.getClass());List<ParameterMapping> parameterMappings = sqlSource.getBoundSql(parameterObject).getParameterMappings();metaStatementHandler.setValue("delegate.boundSql.sql", sqlSource.getBoundSql(parameterObject).getSql());metaStatementHandler.setValue("delegate.boundSql.parameterMappings", parameterMappings);}// 调用原始statementHandler的prepare方法statementHandler = (StatementHandler) metaStatementHandler.getOriginalObject();statementHandler.prepare((Connection) invocation.getArgs()[0]);// 传递给下一个拦截器处理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) {}private SqlSource buildSqlSource(Configuration configuration, String originalSql, Class<?> parameterType) {SqlSourceBuilder builder = new SqlSourceBuilder(configuration);return builder.parse(originalSql, parameterType, null);}
}

StatementHandler的默认实现类是RoutingStatementHandler,因此拦截的实际对象是它。RoutingStatementHandler的主要功能是分发,它根据配置Statement类型创建真正执行数据库操作的StatementHandler,并将其保存到delegate属性里。由于delegate是一个私有属性并且没有提供访问它的方法,因此需要借助MetaObject的帮忙。通过MetaObject的封装后我们可以轻易的获得想要的属性。

在上面的方法里有个两个循环,通过他们可以分离出原始的RoutingStatementHandler(而不是代理对象)。

有了插件帮你生成sql语句后,mapper配置文件里单表的增删改查部分就不需要再配置sql代码了,但由于插件需要通过id来生成不同类型的sql语句,因此必要的配置还是需要的,而且相应的id必须是下面的这几个(区分大小写):

	<update id="update" parameterType="UserDto"></update><insert id="insert" parameterType="UserDto"></insert><delete id="delete" parameterType="UserDto"></delete><select id="select" parameterType="UserDto" resultType="UserDto""></select>

SqlBuilder

SqlBuilder的相应方法接受一个dto对象作为参数,它们根据这个对象的属性值和配置的注解生成相应的sql。

@TableMapperAnnotation(tableName = "t_user", uniqueKeyType = UniqueKeyType.Single, uniqueKey = " userid ")
public class UserDto {@FieldMapperAnnotation(dbFieldName = "userid", jdbcType = JdbcType.INTEGER)private Integer userid;@FieldMapperAnnotation(dbFieldName = "username", jdbcType = JdbcType.VARCHAR)private String username;...
}

这个对象包含了两种注解,一个是TableMapperAnnotation注解,它保存了表名、唯一键类型和构成唯一键的字段;另一个是FieldMapperAnnotation注解,它保存了数据库字段名和字段类型信息。这两个注解都是必须的。SqlBuilder生成sql时会用到他们,下面以生成insert语句的方法为例,其他方法类似:

    public static String buildInsertSql(Object object) throws Exception {if (null == object) {throw new RuntimeException("Sorry,I refuse to build sql for a null object!");}Map dtoFieldMap = PropertyUtils.describe(object);// 从参数对象里提取注解信息TableMapper tableMapper = buildTableMapper(object.getClass());// 从表注解里获取表名等信息TableMapperAnnotation tma = (TableMapperAnnotation) tableMapper.getTableMapperAnnotation();String tableName = tma.tableName();StringBuffer tableSql = new StringBuffer();StringBuffer valueSql = new StringBuffer();tableSql.append("insert into ").append(tableName).append("(");valueSql.append("values(");boolean allFieldNull = true;// 根据字段注解和属性值联合生成sql语句for (String dbFieldName : tableMapper.getFieldMapperCache().keySet()) {FieldMapper fieldMapper = tableMapper.getFieldMapperCache().get(dbFieldName);String fieldName = fieldMapper.getFieldName();Object value = dtoFieldMap.get(fieldName);// 由于要根据字段对象值是否为空来判断是否将字段加入到sql语句中,因此DTO对象的属性不能是简单类型,反而必须是封装类型if (value == null) {continue;}allFieldNull = false;tableSql.append(dbFieldName).append(",");valueSql.append("#{").append(fieldName).append(",").append("jdbcType=").append(fieldMapper.getJdbcType().toString()).append("},");}if (allFieldNull) {throw new RuntimeException("Are you joking? Object " + object.getClass().getName()+ "'s all fields are null, how can i build sql for it?!");}tableSql.delete(tableSql.lastIndexOf(","), tableSql.lastIndexOf(",") + 1);valueSql.delete(valueSql.lastIndexOf(","), valueSql.lastIndexOf(",") + 1);return tableSql.append(") ").append(valueSql).append(")").toString();}

plugin的实现

 

    public Object plugin(Object target) {// 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的// 次数if (target instanceof StatementHandler) {return Plugin.wrap(target, this);} else {return target;}}

 

源码

点击下载

 

http://www.jmfq.cn/news/5045635.html

相关文章:

  • 建设部网站官网施工合同文本/网站关键词排名优化系统
  • 建公司网站需要哪些资料/宁波seo服务快速推广
  • 松江网站开发/老铁外链
  • 做海淘是在哪个网站/微信朋友圈广告怎么推广
  • 建站abc和凡科哪个好用/企业网络推广软件
  • cento安装wordpress/槐荫区网络营销seo
  • 网站聊天工具代码/首页优化排名
  • 如何构思公司网站/seo分析seo诊断
  • 西安建设集团网站/怎么自己做一个网站
  • 上海中国建设银行招聘信息网站/做优化关键词
  • 转入已备案网站/企业网站页面设计
  • 做音乐网站要什么源码/社群营销
  • seo建设网站/网络舆情监测系统软件
  • 网站如何实现微信登录界面/深圳华强北
  • 网站设计需求/百度怎么发布自己的广告
  • 秦皇岛网站制作/营销推广活动策划
  • 网站建设详细的步骤有哪些/可靠的网站优化
  • 乌鲁木齐网站技术服务电话/网站开发详细流程
  • 甘肃省城乡与建设厅网站首页/百度查询网
  • 安徽建站平台/郑州网络营销顾问
  • 温州微网站制作哪里有/关键词是什么意思
  • wordpress主题操作/seo零基础教学视频
  • 普通网站设计/全渠道营销管理平台
  • 桂林做旅游网站失败的网站/站长之家官网登录入口
  • 查看网站是什么语言做的/百度竞价在哪里开户
  • 做淘宝网站用什么软件/百度指数查询官网入口登录
  • 秦皇岛网站团队/企业推广宣传方式
  • 福州免费建站品牌企业/seo管理
  • wordpress 翻译文件/优化大师哪个好
  • 西安的电商网站设计/百度推广seo优化