mybatis宝藏笔记(建议反复查阅)

MyBatis

mybatis概述

mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc, 使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。

mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。

mybatis环境搭建(基础)

  • 使用maven创建项目

    • 先建一个数据库的表用来测试(自己动手)

    • 添加配置

      <!--pom.xml-->
      <!--这里只是添加其中一个依赖的建议,具体可以看mybatis官网,下载来的依赖一般放在默认的.m2下的repository文件夹里面-->
      <!--以下版本号均为参考-->
      <dependencies>
      	<dependency>
          	<groupId>org.mybatis</groupId>
              <artifactId>mybatis</artifactId>
              <version>3.4.5</version>
          </dependency>
          <dependency>
          	<groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.6</version>
          </dependency>
      <!--下面两个依赖是建议性的,一般工程都会有-->
           <dependency>
          	<groupId>log4j</groupId>
              <artifactId>log4j</artifactId>
              <version>1.2.12</version>
          </dependency>
           <dependency>
          	<groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.10</version>
          </dependency>
      </dependencies>    
      
    • 编写mybatis核心配置文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
          <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
                      <property name="url" value="jdbc:mysql://localhost:3306/demo?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                      <property name="url" value="${url}"/>
                      <property name="username" value="root"/>
                      <property name="password" value="root"/>
                  </dataSource>
              </environment>
          </environments>
      </configuration>
      <!--property属性填自己的就行了,放在resource包下,名字随便取。&amp;是转义符&的意思-->
      
    • 连接idea内置默认的数据库工具进行测试

      打开idea右边的Database工具,打开的方框的左上角添加Data source选中mysql,进去后在右侧直接输入账号密码(记得开启mysql服务器)。测试连接,成功后在上面一点的Schemas选项卡里面勾上你的测试用数据库,确定后你的database工具就成了一个内置的低配数据库用户管理软件,可以看到相关数据库的信息。

    • 这里测试连接的时候有可能要求下载driver文件,让他下载就行了,若遇到设置时区问题:

      //这里我直接在mysql命令行里操作
      //从cmd进入mysql
      mysql -uroot -p
      //查看时区
      show variables like'%time_zone';
      //若time_zone显示System说明没有配置
      set global time_zone ='+8:00';
      //设置了要重开mysql就可以看到时区设置成功。
      
    • mybatis连接了数据库字段和java实体类,所以创建java实体类。

      public class UserBean implements Serializable{
          //相应的数据
          //相应的getter方法
          //相应的setter方法
          //相应的toString方法
      }
      
    • 注意点

      • 这里的UserBean一定要有无参构造函数,要么有参无参一起写,要么都别写

      • 字段名和实体类属性相同则是通过反射传值,字段名若和方法名对应则是通过setter方法传值,两个都写优先setter方法。

      • 若字段名和属性名或者方法名都不匹配,则需要通过mapper的映射

        <resultMap type = "com.qjl.demo.pojo.UserBean" id="myMapper">
        		<id property="某属性名" column="某字段名" />
        		<id property="某属性名" column="某字段名" />
        		<id property="某属性名" column="某字段名" />
        </resultMap>
        <!--这段代码添加到所有的select标签的下面(同级),type写实体类名,id自己取一个,在需要用的select标签里面添加属性resultMap=“myMapper”-->
        <select resultMap="myMapper"/>
        <!--这样即可应用该映射-->
        
    • 创建dao文件夹用于存放dao接口。

      //IUserBeanDao
      public interface IUserBeanDao{
          List<UserBean> getUserBean();
      } 
      
    • 在resource下建一个mapperImpl包,再建一个UserMapper.xml文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.qjl.demo.dao.IUserBeanDao">
          <select id="getUserBean" resultType="com.qjl.demo.pojo.UserBean">
              select * from resource
        </select>
      </mapper>
      <!--这个文件相当于一个实现了IUserBeanDao的类,namespace指定了接口,select标签里的id指定要重写的方法,resultType指定返回的类型,select里面是sql语句-->
      
    • 要是上面这个文件没有放在Resource文件夹里面或者没有和mybatis-config.xml文件同级

      则需要在mybatis-config.xml文件里面配置(上面有)

      <!--configuration标签里面,放最后就行了-->
      <!--注意是斜杠不是点-->
      <mappers>
          <mapper resource="org/mybatis/example/BlogMapper.xml"/>
      </mappers>
      <!--可以*.xml通配-->
      
  • 创建一个Utils类专门操作数据库(获得SqlSession对象)

    //首先获得工厂类
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sql = new SqlSessionFactoryBuilder().build(inputStream);
    //获得SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    

    SqlSession sqlSession = sqlSessionFactory.openSession(ture);开启自动事务管理。

    • 进行测试,获取数据库信息转化成实体类

      SqlSession sqlSession = MybatisUtils.getSession();
      IRes res = sqlSession.getMapper(IRes.class);
      List<Src> list = res.getRes();
      for (Src src : list) {
            System.out.println(src);
      }
      sqlSession.close();
      //1、2行还可以用下面的语句代替
      //List<UserBean> list = sqlSession.selectList("com.qjl.demo.dao.UserBean");
      

mybatis进阶

  • 数据库查询

    • 增删改查

      <!--parameterType="int"可以传入参数-->
      <select id="getId" resultType="com.qjl.demo.pojo.Src" parameterType="int">
              select * from resource where src_id = #{id}
      </select>
      <!--#{id}若只有一个则会自动匹配getter方法名,随便写,parameterType只有一个基本类型,甚至可以不用写-->
      
      <insert id="insert" parameterType="com.qjl.demo.pojo.Src">
              insert into resource (src_id,src_url) values (#{id},#{url})
      </insert>
      <!--可以传入自定义的实体类,记得#{id}至少和实体类属性名或者getter方法名其中一个相对应就行-->
      <delete id="delete" parameterType="int">
              delete from resource where src_id = #{id}
      </delete>
      <update id="update" parameterType="com.qjl.demo.pojo.Src">
              update resource set src_url=#{url} where src_id=#{id};
      </update>
      
      SqlSession sqlSession = MybatisUtils.getSession();
      IRes iRes = sqlSession.getMapper(IRes.class);
      iRes.insert(new Src(123215463,"123456"));
      //增删改查调用相应方法就可以了
      sqlSession.commit();
      sqlSession.close();
      

      别忘了提交事务sqlSession.commit( );

    • 使用map来传参

        <insert id="insert" parameterType="map">
                insert into resource (src_id,src_url) values (#{id},#{url})
        </insert>
      
        //dao
        void insert(Map<String,Object> map);
        //业务
        SqlSession sqlSession = MybatisUtils.getSession();
        IRes iRes = sqlSession.getMapper(IRes.class);
        Map<String,Object> map = HashMap<String,Object>();
        map.input("id",123);
        map.input("url","information")
        iRes.insert(map);
      

      作用是#{id}通过map的key来指定,并且参数灵活可变

      多参数时要么传实体类要么传map,或者可以使用getList(@Param(“id”) int id,@Param(“pwd”) int pwd)

      使用@Param后#{ }绑定就以它为准,同时mapper.xml文件中不用再设置parameterType属性了

  • mybatis-config.xml配置优化

    • 使用${ }动态绑定 变量

      <!--在mybatis-config.xml同级创建jdbc.properties文件-->
      driver=com.mysql.jdbc.Driver
      url=jdbc:mysql://localhost:3306/demo?useSSL=false&useUnicode=true&characterEncoding=UTF-8
      username=root
      password=root
      
      <!--注意mybatis-config.xml文件有顺序,请在environment标签前面添加properties标签引入上面的变量文件-->
      <!--properties标签里面的property属性一样可用于设置变量,若冲突会使用外部配置文件-->
      <properties resource="jdbc.properties">
      	<property name="username" value="root"/>
          <property name="password" value="root"/>
      </properties>
      <!--这样之后就可以通过${ }来绑定变量了-->
      <environments default="development">
          <environment id="development">
              <transactionManager type="JDBC"/>
              <dataSource type="POOLED">
                  <property name="driver" value="${driver}"/>
                  <property name="url" value="${url}"/>
                  <property name="username" value="${username}"/>
                  <property name="password" value="${password}"/>
              </dataSource>
          </environment>
      </environments>
      

      优先使用外部配置文件

    • 设置别名替代全限定符

      • 配置的方式

        <!--mybatis-config.xml文件中添加别名-->
        <!--第一种,是自己设定别名-->
        <typeAliases>
        	<typeAlias alias="demo1" type="com.qjl.demo.demo1"/>
            <typeAlias alias="demo2" type="com.qjl.demo.demo2"/>
        </typeAliases>
        <!--第二种,更自动化,扫描实体类的包,在没有注解的情况下,别名就是实体类名称(首字母大小写都可以)-->
        <typeAliases>
        	<package name="com.qjl.demo.pojo"/>
        </typeAliases>
        

        在mybatis-config.xml文件里面配置的属性都是有顺序的,这个typeAliases标签是在上面properties标签的后面,排在第三个(第二个是settings标签),没事idea里面有提示的,错了会告诉你应该放第几个。

      • 注解的方式

        @Alias("user")
        public class UserBean{
            ...
        }
        //注解建议和上面扫描包的方式一起使用,有特殊需要加上注解就可以自定义别名(注解优先)。
        

        基本类型比如像int默认映射为Integer,要使用int请在前面加 _ (例如 _int)

    • settings设置

      <!--常用-->
      <settings>
      	<setting name="logImpl" value="STDOUT_LOGGING"/><!--开启默认log记录方式-->
          <setting name="mapUnderscoreToCamelCase" value="true"/><!--字段属性之间驼峰命名映射-->
      </settings>
      
    • mapper映射

      <!--上面讲过的使用直接映射的方法-->
      <mappers>
      	<mapper resource="com.qjl.demo.XXXMapper.xml"/>
      </mappers>
      <!--指定映射器接口完成映射-->
      <mappers>
      	<mapper class="com.qjl.demo.UserDao"/>
      </mappers>
      <!--包的扫描引入-->
      <mappers>
      	<package name="com.qjl.demo"/>
      </mappers>
      

      注意第二和第三种方法:接口和他的mapper配置文件必须同名并且在同一个包下面(UserDao改成UserMapper,UserMapper.xml放到dao文件夹下)

    • 生命周期和作用域

      生命周期讲的就是SqlSessionFactoryBuilder只使用一次,就是用来创建SqlSessionFactory,而SqlSessionFactory随程序运行诞生,随程序结束消亡,全程只有一个(设置为静态变量)。SqlSessionFactory获得的SqlSession不是线程安全的,每个线程需要单独一个SqlSessison为其工作,用完记得关闭。

    • resultMap结果集映射

      <!--上面讲过了,这里介绍起别名的方法-->
      <select ...>
          select name,password as pwd from table 
      </select>
      <!--这里的password是字段名,pwd是实体类属性名,这样就可以映射在一起-->
      
  • 使用日志

    • 内置日志

      <settings>
      	<setting name="logImpl" value="STDOUT_LOGGING"/>
      </settings>
      
    • 使用log4j

      <settings>
      	<setting name="logImpl" value="LOG4J"/>
      </settings>
      
      <!--依赖-->
      <dependencies>
      	<dependency>
          	<groupId>log4j</groupId>
              <artifactId>log4j</artifactId>
              <version>1.2.17</version>
          </dependency>
      </dependencies>
      <!--在resources文件夹下配置log4j.properties文件-->
      
      #这个是log4j.properties文件,只是推荐,具体调配根据需求,可以参考文档。
      ### set log levels ###
      log4j.rootLogger=DEBUG,stdout,info,warn,error
      ### console ###
      log4j.appender.stdout=org.apache.log4j.ConsoleAppender
      log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
      log4j.appender.stdout.layout.ConversionPattern=[${projectName}] [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %n%m%n
      ### info ###
      log4j.logger.info=info
      log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
      log4j.appender.info.File=${webapp.root}/logs/${projectName}_info.log
      log4j.appender.info.DatePattern='_'yyyy-MM-dd'.log'
      log4j.appender.info.Append=true
      log4j.appender.info.bufferSize=1024
      log4j.appender.info.Threshold=INFO
      log4j.appender.info.layout=org.apache.log4j.PatternLayout
      log4j.appender.info.layout.ConversionPattern=[${projectName}] [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %n%m%n
      #warn log
      log4j.logger.warn=warn
      log4j.appender.warn=org.apache.log4j.DailyRollingFileAppender
      log4j.appender.warn.DatePattern='_'yyyy-MM-dd'.log'
      log4j.appender.warn.File=./logs/${projectName}_warn.log
      log4j.appender.warn.Append=true
      log4j.appender.warn.Threshold=WARN
      log4j.appender.warn.layout=org.apache.log4j.PatternLayout
      log4j.appender.warn.layout.ConversionPattern=[${projectName}] [%p] [%d{yyyy-MM-dd HH:mm:ss a}] [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
      
      ### error ###
      log4j.logger.error=error
      log4j.appender.error=org.apache.log4j.DailyRollingFileAppender
      log4j.appender.error.File=${webapp.root}/logs/${projectName}_error.log
      log4j.appender.error.DatePattern='_'yyyy-MM-dd'.log'
      log4j.appender.error.Append=true
      log4j.appender.error.Threshold=ERROR
      log4j.appender.error.layout=org.apache.log4j.PatternLayout
      log4j.appender.error.layout.ConversionPattern=[${projectName}] [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %m%n [Thread: %t][ Class:%c  Method: %l ] %n
      
      ###显示SQL语句部分
      log4j.logger.org.mybatis=DEBUG
      #log4j.logger.com.mybatis.common.jdbc.SimpleDataSource=DEBUG
      #log4j.logger.com.mybatis.common.jdbc.ScriptRunner=DEBUG
      #log4j.logger.com.mybatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
      log4j.logger.java.sql.Connection=DEBUG
      log4j.logger.java.sql.Statement=DEBUG
      log4j.logger.java.sql.PreparedStatement=DEBUG
      
      //上面是通用的方法,接下来我们使用log代替system.out
      static Logger logger = Logger.getLogger(test.class); //当前的类对象
      logger.info("this is info");
      logger.error("this is error");
      //输出 [com.qjl.demo.User]-this is info
      
  • 分页

    • limit实现:SQL语句里面的limit,学过sql就知道

    • RowRounds实现(了解一下就行)

      //直接调用sqlSession的方法来获取实体类。
      //具体到dao层接口的方法名。
      RowBounds rowBounds = new RowBounds(1,2);
      //org.apache.ibatis.session包下面,1是offset,2是limit。
      List<User> list = sqlSession.selectList("com.qjl.dao.mapper类.方法名"null,rowBounds);
      //这么处理以后就不用在dao层接口方法里传参数了。
      
  • 使用注解开发

    • mybatis-config.xml配置以及接口注解

      <mappers>
          <mapper class="com.qjl.dao.UserDao"/>
      </mappers>
      
      //使用注解代替mapper.xml,但是只适合简单的语句
      public interface UserDao{
          @Select("select * from resource")
          List<User> getUserList();
      }
      
  • #{ }和${ }的区别

    #{ }会将传入的值转变成String类型,KaTeX parse error: Expected 'EOF', got '#' at position 11: { }则不会,意味着#̲{ }若是限定int只能传in…{ }没法限定int,它只能传进来String型,所以使用#{ }可以防止sql注入

    注意:mybatis排序时使用order by动态参数时使用的是${ }而不是#{ }

  • lombok偷懒神器(别用)

    首先添加依赖,自己去maven官网找repository依赖

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class UserBean{
        String name;
        int age;
        boolean sex;
    }
    //@Data注解会帮你写了getter、setter、toString、无参构造,@Getter写类上对所有属性生效,也可以单独对某个属性使用。
    //其他自己研究吧,就是帮你偷懒写实体类的工具。
    

    建议别用,什么东西嘛,注解真的是对新手超级超级超级超级不友好的东西。而且侵入性很强,拿过来的代码还得到处装包。

  • 嵌套查询

    • 子查询

      <!--场景:一个用户拥有多辆车,用户id对应汽车的userId,下面实现子查询实现转对象-->
      <!-- 
      public class Car{
      	int id;
      	int color;
      	User userId;
      }
      public class User{
      	int id;
      	String name;
      	String desc;
      }
      -->
      <resultMap id="carMap" type="com.qjl.pojo.Car">
      	<association property="userId" column="uId" javaType="com.qjl.pojo.User" select="getUser"/>
      </resultMap>
      <select id="getCar" resultMap="carMap" resultType="Car">
      ...
      </select>
      <select id="getUser" resultType="User">
      ... #{uId}
      </select>
      
    • 关联查询

      <!--关联查询其实两个表的信息都会同时查出来,只要匹配就行了-->
      <select id="getCar" resultMap="carMap">
      	select car.id, car.color,user.id from car,user where car.id = user.id
      </select>
      <!--该sql语句其实将两个表所有信息都查询出来了,只不过我们选择呈现了car.id, car.color,user.id,所以其实不用子查询,因为所有信息已经有了,只要做一个结果集映射就行了-->
      <resultMap id="carMap" type="com.qjl.pojo.User">
      	<association property="userId"  javaType="com.qjl.pojo.User">
          	<result property="id" column="id"/>
              <!--这里可以看成是等于条件,property是User的id,column是前面user.id对应上了-->
          </association>
      </resultMap>
      <!--如果在select里面去了别名,column要用别名来映射-->
      
    • 集合查询

      <!--和关联查询相同,association改成collection就行-->
      <collection property="集合属性" javaType="ArrayList" ofType="泛型类">
      	<result property="泛型类属性" column="字段名"/>
      </collection>
      <!--子查询就自己研究了,个人认为这种比较好-->
      

      tips:UUID.randomUUID().toString().replaceAll("-","");可以生成一段随机ID

  • mybatis缓存

    • 一级缓存

      一级缓存默认开启,比如两次查询获得的对象是同一个,而insert、update、delete方法会刷新缓存,并且不定时刷新,不受我们控制。

      手动清理缓存:sqlSession.clearCache( );

    • 二级缓存

      二级缓存也叫全局缓存,二级缓存范围更加大,不止在同一个SQLSession,而是在一个mapper.xml文件里面生效

      开启的方式:<mapper>标签里面第一行添加上<cache/>就行了,具体设置如下

      <cache
             eviction="FIFO"
             flushInterval="60000"
             size="512"
             readOnly="true"/>
      <!--60秒刷新,最多可以有512个引用,只读属性,建议在setting里面开启设置如下所示(不写也行)-->
      <setting name="cacheEnabled" value="true">
      

      afterAll,二级缓存就是两个sqlSession之间跨越调用同一个缓存,前提是前一个缓存已经关闭


完结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值