zoukankan      html  css  js  c++  java
  • mybatis框架

    一、框架概述:

    mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。 mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。 采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。

    二、工作原理

    首先,SqlSessionFactoryBuilder根据mybatis-config.xml配置文件(也可以用Java文件配置的方式,需要添加@Configuration)来构建SqlSessionFactory(SqlSessionFactory是线程安全的);

    然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交,最后关闭SqlSession。

    说明:SqlSession是单线程对象,因为它是非线程安全的,是持久化操作的独享对象,类似jdbc中的Connection,底层就封装了jdbc连接。

    三、编程步骤

    package com.itheima.test;
    
    import com.itheima.dao.IUserDao;
    import com.itheima.domain.QueryVo;
    import com.itheima.domain.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.InputStream;
    import java.util.Date;
    import java.util.List;
    
    /**
     * @author 黑马程序员
     * @Company http://www.ithiema.com
     *
     * 测试mybatis的crud操作
     */
    public class MybatisTest {
    
        private InputStream in;
        private SqlSession sqlSession;
        private IUserDao userDao;
    
        @Before//用于在测试方法执行之前执行
        public void init()throws Exception{
            //1.读取配置文件,生成字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.获取SqlSessionFactory
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
            //3.获取SqlSession对象
            sqlSession = factory.openSession();
            //4.获取dao的代理对象
            userDao = sqlSession.getMapper(IUserDao.class);
        }
    
        @After//用于在测试方法执行之后执行
        public void destroy()throws Exception{
            //提交事务
            sqlSession.commit();
            //6.释放资源
            sqlSession.close();
            in.close();
        }
    
        /**
         * 测试查询所有
         */
        @Test
        public void testFindAll(){
            //5.执行查询所有方法
            List<User> users = userDao.findAll();
            for(User user : users){
                System.out.println(user);
            }
    
        }
    }
    View Code

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

      Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,
    举例:com.mybatis3.mappers.StudentDao.findStudentById,
    可以唯一找到namespace为com.mybatis3.mappers.StudentDao
    下面id = findStudentById的MappedStatement。
    在Mybatis中,每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象。

    Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。
    Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

    五、延迟加载

    问题:在一对多中,当我们有一个用户,它有100个账户。

    在查询用户的时候,要不要把关联的账户查出来?

    在查询账户的时候,要不要把关联的用户查出来?

    在查询用户时,用户下的账户信息应该是,什么时候使用,什么时候查询的。

    在查询账户时,账户的所属用户信息应该是随着账户查询时一起查询出来。

    什么是延迟加载

    在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)

    什么是立即加载

    不管用不用,只要一调用方法,马上发起查询。

    在对应的四种表关系中:一对多,多对一,一对一,多对多

    一对多,多对多:通常情况下我们都是采用延迟加载。

    多对一,一对一:通常情况下我们都是采用立即加载。

    在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。

    六、多表查询

    通过在resultMap里面配置association节点配置一对一的类就可以完成一对一查询。
    通过在resultMap里面的collection节点配置一对多的类就可以完成一对多查询。

    七、一级缓存、二级缓存

    一级缓存:cache作用域为session。同一session,发三次同样的SQL,只有一次查DB,其余直接cache返回。同一session,如果三次中间有一次写入操作,则缓存失效。

    二级缓存:cache跨session。三个session,发三次同样的SQL,只有一次查DB,其余直接cache返回。

      ①、一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

      ②、二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

     总结:

  • 相关阅读:
    你所不知道的 CSS 阴影技巧与细节
    %date~0,4%和 %time~0,2%等用法详解
    计算程序执行时间
    GDI
    IO
    字符串拼凑批量Insert SQL语句神BUG
    用逗号分隔的数据转换到数组
    MVC ViewBag传值
    接口和抽象类对比
    Partial 同一个命名空间下写两个类名一样的类
  • 原文地址:https://www.cnblogs.com/jingpeng77/p/13160428.html
Copyright © 2011-2022 走看看