美文网首页
mybatis相关

mybatis相关

作者: go_2021 | 来源:发表于2022-01-25 10:14 被阅读0次

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

封装流程

mybatis在jdbc上进行封装

  • 把数据库的链接 关闭的操作 进行隐藏执行 不用显性执行
  • 抽离出了sql 到持久层xml文件中
  • 事务
  • 缓存的支持(本地缓存,微服务会有脏数据)
    • 一级缓存 默认开启 sqlsession生命周期 缓存查询结果 写入删除 不能跨sql导致脏数据
    • 二级缓存 默认关闭 namespace生命周期 缓存查询结果 写入删除

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

延时加载

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

#$区别
  • #是预编译处理,会加引号。
    • ac.company_id IN (21212,21211) 会变成("21212,21211") 导致查询数据错误。
    • order by order_id->order by "order_id"
  • $是字符串替换
map接受数据
  • 好处:方便 不用写接受 entity
  • 不好的地方:
    • 结果未知,不直观,转换会出问题(long->int)
    • null的字段不返回(处理数据空指针)
      mybatis:configuration:call-setters-on-nulls: true
    • Mybatis中表中 tinyint 1 会自动转为 boolean
      • 链接配置:?tinyInt1isBit=false
      • 改为tinyint 2 上线之后 一样的代码 还是会转换为 boolean。。 改为mysql 为 int类型
默认类型的一些研究

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

  • 用tk.mybatis或者mybatisPlus,不创建xml,直接创建实体接受mysql的数据。
  • 在xml配置文件里指定字段的类型:
<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来深分页查询,但是需要是有顺序的记录。

相关文章

  • spring整合mybatis-XML形式

    Spring-MyBatis Spring整合MyBatis 导入包 spring相关包 mybatis相关包 m...

  • SSM(Spring+SpringMVC+MyBatis)整合记

    项目结构 依赖jar包 mybatis 相关 mybatis-3.4.1.jar mybatis-spring-1...

  • Spring之整合MyBatis

    十一、整合MyBatis 目录: 导入相关jar包、MyBatis代码编写、MyBatis-Spring 1.导入...

  • mybatis 相关

    SpringMVC 注解事务 在需要事务的方法上,添加注解 添加配置 如果发现事务未生效,请确认@Transact...

  • Mybatis 相关

    一、#{}和${}的区别是什么? 理解: 二、怎么处理实体类中的属性名和表中的字段名不一致? 三、 模糊查询lik...

  • mybatis相关

    不要试图挑战锻炼自己的自律,要想着把欲望彻底消除。 封装流程 mybatis在jdbc上进行封装 把数据库的链接 ...

  • 2020-04-20 Mybatis相关知识

    Mybatis相关知识 Mybatis之多参传递 注解方式传递参数 1.在mappper.xml中编写相关sql语...

  • Mybatis,hibernate相关

    Mybatis相关 1.Mybatis是什么? 2.为什么选择Mybatis? 3、#{}和${}的区别是什么? ...

  • Mybatis.hibernate相关

    Mybatis相关 1.Mybatis是什么? 2.为什么选择Mybatis? 3、#{}和${}的区别是什么? ...

  • Java面试——MyBatis 相关

    Java面试——MyBatis 相关 MyBatis原理 1,MyBatis 是一个被广泛应用的持久化框架。先创建...

网友评论

      本文标题:mybatis相关

      本文链接:https://www.haomeiwen.com/subject/ebdjfrtx.html