mybatis相关

2022-01-25  本文已影响0人  go_2021

不要试图挑战锻炼自己的自律,要想着把欲望彻底消除。

封装流程

mybatis在jdbc上进行封装


batch是批量插入,缓存编译之后的sql,多条一并执行。

延时加载

在xml中配置,a表对b表关联,可以实现用到b表数据时在去获取b表的数据。
动态代理cglib实现的。

#$区别
map接受数据
默认类型的一些研究

一般我们用mybatis有几种情况:

<result column="bank_account" property="bankAccount" jdbcType="BIGINT" />

但是我看我们公司的代码有的是在xml里Map接收数据,没有配置字段到实体类型的映射,这种情况字段映射的类型是未知的,如果映射为Long,用(Interger)强转的方式映射数据,就会报错:

Exception in thread "main" java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer

这种问题。我就遇到过这个问题,所以就比较好奇具体是如何映射的,通过debug一层层寻找发现逻辑在 com.mysql.jdbc.ResultSetMetaData类的 getClassNameForJavaType方法中:

static String getClassNameForJavaType(int javaType, boolean isUnsigned, int mysqlTypeIfKnown, boolean isBinaryOrBlob, boolean isOpaqueBinary,
            boolean treatYearAsDate) {
        switch (javaType) {
            case Types.BIT:
            case Types.BOOLEAN:
                return "java.lang.Boolean";
            case Types.TINYINT:
                if (isUnsigned) {
                    return "java.lang.Integer";
                }
                return "java.lang.Integer";
            case Types.SMALLINT:
                if (isUnsigned) {
                    return "java.lang.Integer";
                }
                return "java.lang.Integer";
            case Types.INTEGER:
                if (!isUnsigned || mysqlTypeIfKnown == MysqlDefs.FIELD_TYPE_INT24) {
                    return "java.lang.Integer";
                }
                return "java.lang.Long";
            case Types.BIGINT:
                if (!isUnsigned) {
                    return "java.lang.Long";
                }
                return "java.math.BigInteger";
            case Types.DECIMAL:
            case Types.NUMERIC:
                return "java.math.BigDecimal";
            case Types.REAL:
                return "java.lang.Float";
            case Types.FLOAT:
            case Types.DOUBLE:
                return "java.lang.Double";

            case Types.CHAR:
            case Types.VARCHAR:
            case Types.LONGVARCHAR:
                if (!isOpaqueBinary) {
                    return "java.lang.String";
                }
                return "[B";
            case Types.BINARY:
            case Types.VARBINARY:
            case Types.LONGVARBINARY:
                if (mysqlTypeIfKnown == MysqlDefs.FIELD_TYPE_GEOMETRY) {
                    return "[B";
                } else if (isBinaryOrBlob) {
                    return "[B";
                } else {
                    return "java.lang.String";
                }
            case Types.DATE:
                return (treatYearAsDate || mysqlTypeIfKnown != MysqlDefs.FIELD_TYPE_YEAR) ? "java.sql.Date" : "java.lang.Short";
            case Types.TIME:
                return "java.sql.Time";
            case Types.TIMESTAMP:
                return "java.sql.Timestamp";
            default:
                return "java.lang.Object";
        }
    }

这个方法大家可以参考,实际情况还会有不一样的情况。比如:mysql类型是TINYINT,测试和线上就被解析成了不同的类型一个Integer一个boonlean。最后还是让我把mysql字段硬改成了Integer类型 -_~!。

使用tk.mybatis一些经验

insert : 把实体类里面所有字段,拼接sql,执行插入。(需要所有的字段都有默认值,否则不为null的字段会报错)
insertSelective : 只会对指定的字段,拼接sql,执行插入。(没有提到的字段会根据表默认值进行插入)text类型字段,没有默认值,必须指定。
insertList : 是按照insert的方式来的,需要每个字段指定值,否则就是以null形式插入,不为null的字段就会有问题。
@ID 字段注解不能删除,否则.deleteByPrimaryKey(id); 会报错。

MySQL数据存储加密

在一些安全扫描中,如果你的密码是用md5存储的,肯定会说有安全漏洞。我们可以再加一层aes加密,前端传md5,修改和插入时加密存储。登录检查时解密,和前端传值解密。

大致有3种方法,typehandler,plugin, 直接写逻辑。在简单场景中,推荐直接写逻辑。typehandler可以对字段加个封装类,然后加一个转换类,在set和get方法中写入逻辑,配置中指定handler位置。

流式操作

代替普通查询方法,在查询大数据可以避免OOM,每次只传一条数据。游标查询每次会查多条,但是性能会慢很多。
大数据查询分页可以用记录id+limit来深分页查询,但是需要是有顺序的记录。

上一篇 下一篇

猜你喜欢

热点阅读