谈谈那些年踩过的那些坑,蹚过的那些水(一)

达芬奇密码2018-08-08 09:16

0x00mybatis实体采用基本类型

实体类片段如下:

public class City implements Serializable{

    /** 城市主键id */

       private int id;

       /** 城市名 */

       private String name;

mybatis模板片段如下:

<resultMap type="City" id="CityMap">

              <result column="ID"   property="id" jdbcType="INTEGER" />

              <result column="NAME" property="name" jdbcType="VARCHAR" />

产生问题现象:

插入的时候如果id不设置值,默认传入的是0,查询时如果数据库为null查出来的值为0,而不是报异常,造成异常隐藏。

 

解决方案:

应该采用对象类型如Integer

 

0x01mybatis插入非空字段,数据库默认值设置方案

问题写法:

<insert id="insertEntityTransfer" parameterType="com.netease.payment.model.Transfer">

              insert into tb_payment_transfer_order(status,name)

              values(

              #{status,jdbcType=VARCHAR},

              #{name,jdbcType=VARCHAR}

              )

建议写法:

         insert into tb_payment_transfer_order(

              <if test="status!= null">

                     status

              </if>

产生问题的现象:

表中的status字段数据库中设置的为非空,并且默认值为0,模板中没有判断为空,导致插入null值,报异常


0x02、修改序列化对象注意修改字段时会导致历史序列对象无法反序列化

产生问题的现象:

 存在一个资产对象,我们系统采用主动缓存的策略把该对象存在redis中,有需求变更资产对象,修改了字段的类型,忘记调整redis,导致上线过程,历史数据报无法序列化异常

产生问题的原因:

serialVersionUID只能保证增加字段无影响,删除字段修改调整redis的历史数据,或者在redis层做兼容。

serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。

类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的 serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值

显式地定义serialVersionUID有两种用途:

    1、 在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID
    2、 在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID

问题的解决方案:

调整redis中的历史数据,serialVersionUID必须要指定,重写序列化和反序列化。

 

0x03springAop同一个类中两个方法之间调用事务不起作用

错误代码:

         public class A {

            public void noTransationMethod() {

            doTransationMethod();

               }

           @Transactional

            public void doTransationMethod() {

                    // do some transation

                 }

}

问题现象:

外部调用noTransationMethod,期望do some transation 但是没有起作用。

问题原因:

这与AOP的实现有关系,因AOP采用的是动态代理,同一个类中的不同方法之间的调用无法通过扫包拦截。

问题的解决方案:

1、  把方法拆出来放到两个类中

2、  采用实现自感知接口

3、  采用获取代理对象

if (AopUtils.isAopProxy(this))

AopContext.currentProxy()).doTransationMethod ();


0x04Oralcevarchar排序问题,客户端版本号排序

需求:

需要根据客户端的特定版本号区间进行特色处理

问题现象:

对客户端版本采用oracle的比较处理发现获取的版本为非正确版本

比如 获取1.0.0-1.2.0的版本,但是库中存有1.2  1.0  1.0.2这种版本,导致查询失败

解决方案:

1、  规范版本为三位版本号

2、  采用oraclesubstring方法进行处理(不建议,会导致索引失效)

网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者崔翔授权发布。