Mybatis核心技术梳理(持续更新)

中文文档

https://mybatis.org/mybatis-3/zh/index.html

ORM是什么

ORM(Object Relational Mapping),对象关系映射,是一种为了解决关系型数据库数 据与简单Java对象(POJO)的映射关系的技术。简单的说,ORM是通过使用描述对象和 数据库之间映射的元数据,将程序中的对象自动持久化到关系型数据库中。

Mybatis优缺点

优点
与传统的数据库访问技术相比,ORM有以下优点:
基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL 写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态 SQL语句,并可重用。
与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接
很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数 据库MyBatis都支持)。
不同点
能够与Spring很好的集成
缺点
SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底 有一定要求。
SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

MyBatis中#{}和${}的区别

#{}是预编译处理,${}是字符替换。在使用#{}时,MyBatis会将SQL中的#{}替换成?配合PreparedStatement的set方法赋值,这样可以有效的防止SQL注入,保证程序的运行安全。

Mybatis的foreach支持的数据类型

foreach一共有三种类型,分别为List,[](array),Map三种

参数传递方式

匿名传递

List<Employee> selectByGenderAndAge(Short gender,String age );

匿名参数只能使用arg1,arg0,param1,param2类似的形式这种传参方式的缺点是不够灵活,必须严格按照参数顺序来引用

<select id="selectByGenderAndAge" resultMap="BaseResultMap" >
    select *  from employee where gender = #{param1} and age = #{param2}
  </select>

@Param注解

List<Employee> selectByGenderAndAge( @Param("gender") Short gender,@Param("age") String age );  

<select id="selectByGenderAndAge" resultMap="BaseResultMap" > select * from employee where gender = #{gender} and age = #{age} </select> 

Map传递参数

List<Employee> selectByMapParams(Map params); 

<select id="selectByMapParams" resultMap="BaseResultMap" parameterType="map">
  select * from employee where gender = #{gender} and age = #{age}
</select>

java bean传递多个参数

List <Employee> selectByBeans(Employee employee); 

 <select id="selectByBeans" resultMap="BaseResultMap" parameterType="com.wg.demo.po.Employee">
  select
  *
  from employee where gender = #{gender} and age = #{age}
</select>

使用JSON传递参数

List <Employee> findByJSONObject(JSONObject params); 

<select id="findByJSONObject" resultMap="BaseResultMap" parameterType="com.alibaba.fastjson.JSONObject">
  select
  *
  from employee where gender = #{gender} and age = #{age}
</select>

 传递集合类型参数List、Set、Array

List <Employee> findByList(List list);

<select id="findByList" resultMap="BaseResultMap" >
SELECT * from employee where age in
    <foreach collection="list" open="(" separator="," close=")" item="age">
      #{age}
    </foreach>
  </select>

参数类型为对象+集合

@Data
public class Department {
    private Long id;

    private String deptName;

    private String descr;

    private Date createTime;

    List<Employee> employees;

}

List <Employee> findByDepartment(@Param("department")Department department);  

<select id="findByDepartment" resultMap="BaseResultMap" parameterType="com.wg.demo.po.Department">
    SELECT * from employee where dept_id =#{department.id} and age in
    <foreach collection="department.employees" open="(" separator="," close=")" item="employee">
        #{employee.age}
    </foreach>
</select>

核心对象的生命周期

SqlSessionFactoryBuilder:方法作用域
SqlSessionFactory:应用作用域
SqlSession:请求或方法作用域
Mapper:方法

什么是Mybatis

MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。Mybatis可以使用简单的XML或注解来配置和映射原生类型、接口和Java的POJO为数据库中的记录。

动态标签以及执行原理

其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。

if、choose(when/otherwise)、trim(where/set)、foreach

mappers指定路径方式,优先级是什么

resource/url/class/package,package是在第一个 

mybatis的执行器

SimpleExecutor:每次都会重新创建Statement对象
ReuseExecutor:重复使用Statement对象
BatchExecutor:批量处理

Mybatis分页

分页方式:逻辑分页和物理分页
逻辑分页:使用MyBatis自带的RowBounds进行分页,它是一次性查询很多数据,然后在数据中再进行检索
物理分页:自己手写SQL分页或使用分页插件PageHelper,去数据库查询指定条数的分页数据的形式

MyBatis是否支持延迟加载和延迟加载的原理

1.MyBatis支持延迟加载,设置lazyLoadingEnabled=true即可
2.延迟加载的原理的是调用的时候触发加载,而不是在初始化的时候就加载信息
 

注:Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。

它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。

简述Mybatis的插件运行原理,以及如何编写一个插件

1)Mybatis 仅可以编写针对 ParameterHandler、ResultSetHandler、StatementHandler、Executor 这 4 种接口的插件,Mybatis 通过动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler 的 invoke()方法,当然,只会拦截那些你指定需要拦截的方法。

2)实现 Mybatis 的 Interceptor 接口并复写 intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。

一级缓存和二级缓存

https://blog.csdn.net/xiaowanzi_zj/article/details/127490689

1.一级缓存也叫本地缓存,一级缓存是在会话(SqlSession)层面进行缓存的。MyBatis的一级缓存是默认开启的,不需要任何的配置。如果要在同一个会话里面共享一级缓存,这个对象肯定是在SqlSession里面创建的,作为SqlSession的一个属性。DefaultSqlSession里面只有两个属性,Configuration是全局的,所以缓存只可能放在Executor里面维护——SimpleExecutor/ReuseExecutor/BatchExecutor的父类BaseExecutor的构造函数中持有了PerpetualCache。2.二级缓存是用来解决一级缓存不能跨会话共享的问题的,范围是namespace级别的,可以被多个SqlSession共享生命周期和应用同步,二级缓存是CachingExecutor持有的PerpetualCache。

mybatis用到那些设计模式

https://blog.csdn.net/xiaowanzi_zj/article/details/119523658

代理模式、责任链模式、工厂模式、建造者模式、单例模式、适配器模式、模板模式、装饰器模式 

association和collection的区别

association用于一对一和多对一的关系,collection用于一对多的关系

实体类中的属性名和表中的字段名不一样,怎么办

第1种:在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致

<select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”>
   select order_id id, order_no orderno ,order_price price form orders where
order_id=#{id};
</select>

第2种:通过<resultMap>来映射字段名和实体类属性名的一一对应的关系

<select id="getOrder" parameterType="int" resultMap="orderresultmap">
   select * from orders where order_id=#{id}
  </select>
 <resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
   <!–用id属性来映射主键字段–>
    <id property=”id” column=”order_id”>
   <!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–>
    <result property = “orderno” column =”order_no”/>
    <result property=”price” column=”order_price” />
  </reslutMap>

模糊查询like语句该怎么写

List<User> selectUser(@Param("name") String name);

<select id="selectUser" parameterType="string"   resultType="com.entity.User">
        SELECT
            *
        FROM
            t_user
        WHERE
            name LIKE CONCAT('%',#{name},'%')
    </select>

如何获取自动生成的(主)键值

insert 方法总是返回一个int值 - 这个值代表的是插入的行数。
而自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中。
示例:

<insert id=”insertname” usegeneratedkeys=”true” keyproperty=”id”>
         insert into names (name) values (#{name})
 </insert>
 name name = new name();
 name.setname(“fred”);
 int rows = mapper.insertname(name);
 // 完成后,id已经被设置到对象中
 system.out.println(“rows inserted = ” + rows);
 system.out.println(“generated key value = ” + name.getid());

JDBC

https://blog.csdn.net/xiaowanzi_zj/article/details/117049085

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泡^泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值