学习笔记-Mybatis

目录

Mybatis是什么?

 ORM:

一、原理

JDBC连接的5中方法

Mybatis的JDBC连接

 1.1 加载Mapper配置的4中方式

1.2 三种ExcutorType操作

二、缓存机制

2.1 一级缓存

2.2 二级缓存

开启方法如下:

二级缓存什么时候用?

三、Dao

3.1 反射

3.2 JDK动态代理模式

​编辑

3.3 Mybatis Mapper 为什么不需要实现类?

四、分页

Mybatis是如何进行分页的?

分页插件的原理

五、延迟加载

5.1 延迟加载 VS立即加载

5.2 例子

六、动态sql:if  choose  trim  foreach

问题:

Q:JDK 动态代理能否对类代理?

Q:抽象类是否可以 JDK 动态代理?

Q:Mybatis Mapper 接口没有实现类,怎么实现的动态代理?

Q: 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?

Q:Mybatis用了哪些设计模式?

常见面试题

Mybatis是什么?

MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架,被称为半自动化的ORM(Object Relational Mapping)框架

 ORM:

查询结果不同语言之间映射 JDBCTpye - properties - JAVAType

一、原理

推荐文章:

mybatis运行流程_ps酷教程的博客-CSDN博客

JDBC连接的5中方法

JDBC的五种连接方式_DeepMost_的博客-CSDN博客_jdbc连接

Mybatis的JDBC连接

 1.1 加载Mapper配置的4中方式

public class MybatisTest {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = factory.openSession();

        //传统
        String name = "tom";
        List<Map> list1 = sqlSession.selectList("com.demo.mapper.UserMapper.getUserByName",name);

        //这里不再调用SqlSession 的api,而是获得了接口对象,调用接口中的方法。
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<Map> list2 = mapper.getUserByName("tom");

    }
}

1.2 三种ExcutorType操作

ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。(默认)
ExecutorType.REUSE: 这个执行器类型会复用预处理语句。
ExecutorType.BATCH: 这个执行器会批量执行所有更新语句,如果 SELECT 在它们中间执行还会标定它们是 必须的,来保证一个简单并易于理解的行为。

二、缓存机制

先判断是否有二级缓存->一级缓存->数据库

2.1 一级缓存

SqlSession级别的缓存,默认开启  classCacheEnabled = true;

一次会话中的多次相同操作,会先从缓存获取,如果执行了增、删、改会清楚缓存。

2.2 二级缓存

默认是关闭的,二级缓存的对象必须实现序列化接口

开启方法如下:

1、可以通过配置文件开启 核心配置文件mybatis-config.xml

<setting name="cacheEnabled" value="true"/>

2、映射Mapper文件全局

 eviction:回收策略 LRU  FIFO  SOFT  WEAK 

 <cache/> <!-- 本映射文件中的全部查询将开启二级缓存!-->

3、注解的方式实现二级缓存

​ @CacheNamespace //对注解下的接口中的全部查询实现二级缓存

4、mapper文件夹中select标签useCache

<select id="selectByPrimaryKey" useCache="true">

二级缓存什么时候用?

使用二级缓存时需要想好两个问题:
1)对该表的操作与查询都在同一个namespace下,其他的namespace如果有操作,就会发生数据的脏读。
2)对关联表的查询,关联的所有表的操作都必须在同一个namespace。

举个简单的例子:
订单和订单详情,orderMapper、orderDetailMapper。在查询订单详情时我们需要把订单信息也查询出来,那么这个订单详情的信息被二级缓存在orderDetailMapper的namespace中,这个时候有人要修改订单的基本信息,那就是在orderMapper的namespace下修改,他是不会影响到orderDetailMapper的缓存的,那么你再次查找订单详情时,拿到的是缓存的数据,这个数据其实已经是过时的。

三、Dao

3.1 反射

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class c1 = Class.forName("com.example.demo.reflect.ReflectVO");
        Method sayHi = c1.getMethod("sayHi", new Class[] {String.class});
        sayHi.invoke(c1.newInstance(),new Object[] { new String("周杰伦")});

//        //第二种
//        ReflectVO p = new ReflectVO();
//        Class c2 = p.getClass();
//        //第三种
//        Class c3 = ReflectVO.class;
    }
}

3.2 JDK动态代理模式

抽象类能否 JDK 动态代理, 说代码前结论先行,不能!

例子:

public interface Subject {
    String sayHello();
}
public class SubjectImpl implements Subject {
    @Override
    public String sayHello() {
        System.out.println(" Hello World");
        return "success";
    }
}
/**
 * @author 10450
 * @description 动态代理调用处理器
 * @date 2021/12/21 13:49
 */
public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;

    public ProxyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("  进入代理调用处理器 ");
        return method.invoke(target, args);
    }
}
public class ProxyMain {
    public static void main(String[] args) {
        Subject subject = new SubjectImpl();
        Subject proxy = (Subject) Proxy.newProxyInstance(
                        subject.getClass().getClassLoader(),
                        subject.getClass().getInterfaces(),
                        new ProxyInvocationHandler(subject));

        proxy.sayHello();
    }
}

 

3.3 Mybatis Mapper 为什么不需要实现类

超全MyBatis动态代理详解!(绝对干货)_石杉的架构笔记-CSDN博客

Dao接口的工作原理是JDK动态代理

先来说一下 Mybatis 代理工厂中具体生成动态代理类具体逻辑

  1. 根据 .xml 上关联的 namespace, 通过 Class#forName 反射的方式返回 Class 对象(不止 .xml namespace 一种方式)

  2. 将得到的 Class 对象(实际就是接口对象)传递给 Mybatis 代理工厂生成代理对象,也就是刚才 mapperInterface 属性

四、分页

Mybatis是如何进行分页的?

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页

分页插件的原理

在插件的拦截方法内拦截待执行的sql,然后重写sql

举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10

五、延迟加载

5.1 延迟加载 VS立即加载

延迟加载:在真正使用数据的时候才发起查询,不用的时候不查询关联的数据,延迟加载又叫按需查询(懒加载)

立即加载:不管用不用,只要一调用方法,马上发起查询。

使用场景:在对应的四种表关系中,一对多、多对多通常情况下采用延迟加载,多对一、一对一通常情况下采用立即加载。

配置文件中:

lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。
aggressiveLazyLoading当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载(参考 lazyLoadTriggerMethods)。

5.2 例子

Mybatis延迟加载的实现以及使用场景 - 全me村的希望 - 博客园

  <resultMap id="userAccountMap" type="com.example.domain.User">
         <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <collection property="accountList" ofType="com.example.domain.Account" column="id"
                    select="com.example.dao.AccountDao.findAllByUid"/>
    </resultMap>
    <select id="findAll" resultMap="userAccountMap">
        SELECT * FROM USER;
    </select>

 注释绿色部分和没有注释的区别:

 

六、动态sql:if  choose  trim  foreach

问题:

Q:JDK 动态代理能否对类代理?

因为 JDK 动态代理生成的代理类,会继承 Proxy 类,由于 Java 无法多继承,所以无法对类进行代理

Q:抽象类是否可以 JDK 动态代理?

不可以,抽象类本质上也是类,Proxy 生成代理类过程中,会校验传入 Class 是否接口

Q:Mybatis Mapper 接口没有实现类,怎么实现的动态代理?

Mybatis 会通过 Class#forname 得到 Mapper 接口 Class 对象,生成对应的动态代理对象,核心业务处理都会在 InvocationHandler#invoke 进行处理

Q: 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?

答:Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工

Q:Mybatis用了哪些设计模式?

1、构造器模式,build构造

2、装饰者模式,缓存、套娃一样增强

3、

常见面试题

1、什么是 Mybatis?

2、Mybaits 的优点

3、MyBatis 框架的缺点

4、MyBatis 框架适用场合

5、MyBatis 与 Hibernate 有哪些不同?

6、#{}和${}的区别是什么?

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

8、 模糊查询 like 语句该怎么写?

9、通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应,请问,这个 Dao 接口的工作原理是什么?Dao 接口里的方法,参数不同时,方法能重载吗?

10、Mybatis 是如何进行分页的?分页插件的原理是什么?

11、Mybatis 是如何将 sql 执行结果封装为目标对象并返回的?都有哪些映射形式?

12、如何执行批量插入?

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

14、在 mapper 中如何传递多个参数?

15、Mybatis 动态 sql 有什么用?执行原理?有哪些动态 sql?

16、Xml 映射文件中,除了常见的 select|insert|updae|delete标签之外,还有哪些标签?

17、Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?

18、为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?

19、 一对一、一对多的关联查询 ?

20、MyBatis 实现一对一有几种方式?具体怎么操作的?

21、MyBatis 实现一对多有几种方式,怎么操作的?

22、Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?

23、Mybatis 的一级、二级缓存

24、Mapper 编写有哪几种方式?

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一个开源的持久化框架,可以帮助我们将数据从数据库中读取出来,然后转换为Java对象,并将Java对象写入数据库中。 在C#中使用MyBatis,需要先安装MyBatis.Net库,然后在项目中引用该库。接着,我们需要创建一个配置文件,用于配置MyBatis的数据库连接信息、SQL语句等。在配置文件中,我们需要指定一个别名,用于在程序中引用这个配置文件。 接下来,我们需要创建一个映射文件,用于将数据库中的数据映射为Java对象。在映射文件中,我们需要定义一个 resultMap,用于定义Java对象与数据库表之间的关系。我们还需要定义一个 SQL 语句,用于从数据库中读取数据,并将其转换为Java对象。 在程序中,我们需要创建一个 SqlSession 对象,用于执行SQL语句。我们可以通过SqlSession对象调用selectOne、selectList、update、delete等方法,来执行SQL语句,并将结果转换为Java对象或者操作数据库。 下面是一个简单的示例,展示了如何在C#中使用MyBatis: 1. 安装MyBatis.Net库 在Visual Studio中,选择“工具”-“NuGet包管理器”-“程序包管理器控制台”,然后输入以下命令: ``` Install-Package MyBatisNet ``` 2. 创建配置文件 在项目中创建一个名为“SqlMapConfig.xml”的文件,用于配置数据库连接信息、SQL语句等。以下是一个示例配置文件: ``` xml <?xml version="1.0" encoding="utf-8" ?> <sqlMapConfig> <database> <provider name="SqlServer" connectionString="Data Source=localhost;Initial Catalog=mydatabase;User ID=myuser;Password=mypassword;" /> </database> <sqlMap> <map resource="MyMapper.xml"/> </sqlMap> </sqlMapConfig> ``` 其中,provider元素用于指定数据库类型和连接字符串,map元素用于指定映射文件路径。 3. 创建映射文件 在项目中创建一个名为“MyMapper.xml”的文件,用于将数据库中的数据映射为Java对象。以下是一个示例映射文件: ``` xml <?xml version="1.0" encoding="utf-8" ?> <sqlMap namespace="MyMapper"> <resultMap id="MyResultMap" class="MyClass"> <result property="id" column="id"/> <result property="name" column="name"/> </resultMap> <select id="selectById" resultMap="MyResultMap"> SELECT * FROM mytable WHERE id=#id# </select> </sqlMap> ``` 其中,resultMap元素用于定义Java对象与数据库表之间的关系,select元素用于定义SQL语句。 4. 在程序中使用MyBatis 在程序中,我们需要创建一个 SqlSession 对象,用于执行SQL语句。以下是一个示例代码: ``` csharp using IBatisNet.DataMapper; using IBatisNet.DataMapper.Configuration; using IBatisNet.DataMapper.Configuration.Files; // 创建配置文件 DomSqlMapBuilder builder = new DomSqlMapBuilder(); ISqlMapper sqlMapper = builder.Configure(@"SqlMapConfig.xml"); // 执行SQL语句 MyClass obj = sqlMapper.QueryForObject<MyClass>("MyMapper.selectById", new { id = 1 }); ``` 以上是一个简单的示例,展示了如何在C#中使用MyBatis。实际上,MyBatis还有很多其他的用法和功能,需要我们在实际开发中去探索和使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值