<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      mybatis

      <一>:創(chuàng)建核心配置文件mybatis-config.xml(官方推薦名)

      如果一個(gè)屬性在不只一個(gè)地方進(jìn)行了配置,那么,MyBatis 將按照下面的順序來(lái)加載:

      • 首先讀取在 properties 元素體內(nèi)指定的屬性。
      • 然后根據(jù) properties 元素中的 resource 屬性讀取類路徑下屬性文件,或根據(jù) url 屬性指定的路徑讀取屬性文件,并覆蓋之前讀取過的同名屬性。
      • 最后讀取作為方法參數(shù)傳遞的屬性,并覆蓋之前讀取過的同名屬性。

      因此,通過方法參數(shù)傳遞的屬性具有最高優(yōu)先級(jí),resource/url 屬性中指定的配置文件次之,最低優(yōu)先級(jí)的則是 properties 元素中指定的屬性。

      <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuratio        
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"       
      "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <!--configuration核心配置文件--><configuration>
      <properties resource="db.properties"/> //外部關(guān)聯(lián)和內(nèi)部屬性同時(shí)存在時(shí),優(yōu)先外部關(guān)聯(lián)    <typeAliases>
      <!--<typeAlias type="com.whily.pojo.Emp" alias="Emp"/> 限定這個(gè)類的別名--> <package name="com.whily.pojo"/><!--將這個(gè)包下的類的首字母小寫作為別名--> </typeAliases> <!--default-設(shè)置默認(rèn)加載的環(huán)境  --> <environments default="development"> <environment id="development">
            <!-- 設(shè)置事務(wù)管理器 -->
      <transactionManager type="JDBC"/>
                <!-- 配置數(shù)據(jù)源 -->
      <dataSource type="POOLED">
                <!-- 配置數(shù)據(jù)源的屬性 -->
      <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${uid}"/> <property name="password" value="${pwd}"/> </dataSource> </environment> </environments> <!--每一個(gè)Mapper都需要在Mybatis核心配置文件中注冊(cè)--> <mappers> <mapper resource="EmpMapper.xml"/> </mappers> </configuration>

      <二>:創(chuàng)建工具類

      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 java.io.IOException;
      import java.io.InputStream;
      
      //sqlSessionFactory--> sqlSession
      public class MybatisUtils {
          private static SqlSessionFactory sqlSessionFactory;
      
          static {
              try {
                  String resource = "mybatis-config.xml";
                  InputStream inputStream = Resources.getResourceAsStream(resource);
                   sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      
          public static SqlSession getSqlSession() {
              return sqlSessionFactory.openSession();
      
          }
      }

       

      <三>:創(chuàng)建實(shí)體類以及Dao接口

      import org.apache.ibatis.type.Alias;
      
      @Alias(value = "Emp")   //注解別名
      public class Emp {
          private int empid;
          private String name;
          private String username;
          private String password;
          private int deptid;
      
          public Emp(int empid, String name, String username, String password, int deptid) {
              this.empid = empid;
              this.name = name;
              this.username = username;
              this.password = password;
              this.deptid = deptid;
          }
          public Emp() {
          }
          public int getEmpid() {
              return empid;
          }
          public void setEmpid(int empid) {
              this.empid = empid;
          }
          public String getName() {
              return name;
          }
          public void setName(String name) {
              this.name = name;
          }
          public String getUsername() {
              return username;
          }
          public void setUsername(String username) {
              this.username = username;
          }
          public String getPassword() {
              return password;
          }
          public void setPassword(String password) {
              this.password = password;
          }
          public int getDeptid() {
              return deptid;
          }
          public void setDeptid(int deptid) {
              this.deptid = deptid;
          }
          @Override
          public String toString() {
              return "emp{" +
                      "empid=" + empid +
                      ", name='" + name + '\'' +
                      ", username='" + username + '\'' +
                      ", pwd='" + password + '\'' +
                      ", deptid=" + deptid +
                      '}';
          }
      }

      <四>:創(chuàng)建sql語(yǔ)句Mapper.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">
      <!--namespace綁定一個(gè)對(duì)應(yīng)的Dao/Mapper接口-->
      
      <mapper namespace = "com.whily.dao.EmpDao">
      <select id="getEmpList" resultType="Emp">
          select * from employee;
      </select>
      
          <select id="getEmpByid" parameterType="int" resultType="Emp">
      select * from employee where empid=#{id};
          </select>
      
          <insert id="addEmp" parameterType="Emp" >
              insert into employee(empid,name,username,password,deptid)values (#{empid},#{name},#{username},#{password},#{deptid});
          </insert>
          <update id="update" parameterType="Emp">
              update employee set name=#{helloname},username=#{hellousername},password=#{hellopassword},deptid=#{hellodeptid} where empid=#{helloempid};
          </update>
      
          <!--萬(wàn)能Mapper-->
          <delete id="delete"  parameterType="map" >
              delete from employee where empid=#{Helloid};
          </delete>
      
          <select id="getEmpLike" parameterType="map" resultType="Emp">
              select * from employee where name like "%"#{value}"%";
          </select>
      </mapper>

      <五>:創(chuàng)建測(cè)試類

      增刪改一定要提交事務(wù)

       sqlSession.commit();
              sqlSession.close();
      package com.whily.dao;
      
      import com.whily.pojo.Emp;
      import com.whily.utils.MybatisUtils;
      
      import org.apache.ibatis.session.SqlSession;
      import org.junit.Test;
      
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      public class EmpDaoTest {
          @Test
          public void test() {
              //獲取SqlSession對(duì)象
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              //執(zhí)行SQL
      
              //方式一:getMapper
              EmpDao mapper = sqlSession.getMapper(EmpDao.class);
              List<Emp> empList = mapper.getEmpList();
              for (Emp emp : empList) {
                  System.out.println(emp);
              }
              System.out.println("******************");
              //方式二:
              List<Emp> emps = sqlSession.selectList("com.whily.dao.EmpDao.getEmpList");
              for (Emp emp : emps) {
                  System.out.println(emp);
              }
              sqlSession.close();
          }
      
          @Test
          public void getEmpByid() {
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              EmpDao mapper = sqlSession.getMapper(EmpDao.class);
              Emp emp = mapper.getEmpByid(196);
              System.out.println(emp);
              sqlSession.close();
          }
      
          @Test
          public void addEmp() {
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              EmpDao mapper = sqlSession.getMapper(EmpDao.class);
              int emps = mapper.addEmp(new Emp(500, "qqq", "hahaha", "1111", 5));
              if (emps > 0) {
                  System.out.println("成功");
              }
              sqlSession.commit();
              sqlSession.close();
          }
      
          @Test
          public void update() {
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              EmpDao mapper = sqlSession.getMapper(EmpDao.class);
              Map<String, Object> map = new HashMap<String, Object>();
              map.put("helloname", "qqq");
              map.put("hellousername", "qqq");
              map.put("hellopassword", "www");
              map.put("hellodeptid", 1);
              map.put("helloempid", 196);
              int emp = mapper.update(map);
              if (emp > 0) {
                  System.out.println("成功");
              }
              sqlSession.commit();
              sqlSession.close();
          }
      
          @Test
          public void delete() {
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              Map<String, Object> map = new HashMap<String, Object>();
              map.put("Helloid", 500);
              EmpDao mapper = sqlSession.getMapper(EmpDao.class);
              mapper.delete(map);
              sqlSession.commit();
              sqlSession.close();
          }
      
          @Test
          public void getEmpLike() {
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              EmpDao mapper = sqlSession.getMapper(EmpDao.class);
      
              List<Emp> emps = mapper.getEmpLike("%qq%");
              for (Emp emp : emps) {
                  System.out.println(emp);
              }
              sqlSession.close();
          }
      }

       

      六、生命周期

       

       

       

      每一個(gè)Mapper都是一個(gè)業(yè)務(wù)

       

       生命周期和作用域是至關(guān)重要的,因?yàn)殄e(cuò)誤的使用會(huì)導(dǎo)致非常嚴(yán)重的并發(fā)問題。

      SqlSessionFactoryBulider:

      • 一旦創(chuàng)建了SqlSessionFactoryBulider,就不需要他了
      • 局部變量

      SqlSessionFactory:

      • 說白了可以想象為數(shù)據(jù)庫(kù)連接池;
      • SqlSessionFactory一旦被創(chuàng)建就應(yīng)該在應(yīng)用的運(yùn)行期間一直存在,沒有任何理由放棄或重新創(chuàng)建
      • 因此SqlSessionFactory的最簡(jiǎn)作用域是應(yīng)用作用域;
      • 最簡(jiǎn)單的就是單例模式或者靜態(tài)單例模式。

      SqlSession:

      • 連接到連接池的一個(gè)請(qǐng)求
      • SqlSession的實(shí)例不是線程安全的,因此不是共享的,所以他的作用域是請(qǐng)求或方法作用域
      • 用完之后要趕緊關(guān)閉,否則資源被占用!

       

      字段和屬性名不一致

      • 起別名

      7、ResultMap映射:結(jié)果集映射

       <resultMap id="EmpMap" type="Emp">  
              <!--column數(shù)據(jù)庫(kù)的字段  property實(shí)體類的屬性-->
              <result column="empid" property="empid"/>
              <result column="username" property="username"/>
              <result column="deptid" property="deptid"/>
              <result column="name" property="name"/>
              <result column="password" property="pwd"/>  //
          </resultMap>
      
      <select id="getEmpList" resultMap="EmpMap" //對(duì)應(yīng)ResultMap的id值>
          select * from employee;
      </select>
      • resultMap元素是MyBatis中最重要最強(qiáng)大的元素
      • ResultMap的設(shè)計(jì)思想是,對(duì)于簡(jiǎn)單的語(yǔ)句根本不需要配置顯示的結(jié)果映射,而對(duì)于復(fù)雜一點(diǎn)的語(yǔ)句只需要描述他們的關(guān)系就行
      • ResultMap最優(yōu)秀的地方在于,雖然你已經(jīng)對(duì)他相當(dāng)了解了,但根本就不需要顯示地用到他們

      設(shè)置

      <settings>
        <setting name="cacheEnabled" value="true"/>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="multipleResultSetsEnabled" value="true"/>
        <setting name="useColumnLabel" value="true"/>
        <setting name="useGeneratedKeys" value="false"/>
        <setting name="autoMappingBehavior" value="PARTIAL"/>
        <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
        <setting name="defaultExecutorType" value="SIMPLE"/>
        <setting name="defaultStatementTimeout" value="25"/>
        <setting name="defaultFetchSize" value="100"/>
        <setting name="safeRowBoundsEnabled" value="false"/>
        <setting name="mapUnderscoreToCamelCase" value="false"/>
        <setting name="localCacheScope" value="SESSION"/>
        <setting name="jdbcTypeForNull" value="OTHER"/>
        <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
      </settings>

      8、日志

      8.1 日志工廠

      如果一個(gè)數(shù)據(jù)庫(kù)操作出現(xiàn)了異常,我們需要拍錯(cuò)。日志就是最好的幫手

      以前:sout、debug

      現(xiàn)在:日志工廠!    logImpl    指定Mybatis所用日志的具體表現(xiàn),未指定時(shí)將自動(dòng)查找。

       

      • SLF4J
      • LOG4J  (掌握)
      • LOG4J2  
      • JDK_LOGGING
      • STDOUT_LOGGING  (掌握)
      • NO_LOGGING
      • COMMONS_LOGGING

      具體用使用哪一個(gè)日志實(shí)現(xiàn),在設(shè)置中設(shè)定!

       

      STDOUT_LOGGING

       <settings>
              <setting name="logImpl" value="STDOUT_LOGGING"/>  //必須規(guī)范書寫,按官方書寫,不能有空格
          </settings>


      @Test
      public void getEmpLike() {
      SqlSession sqlSession = MybatisUtils.getSqlSession();
      EmpDao mapper = sqlSession.getMapper(EmpDao.class);

      List<Emp> emps = mapper.getEmpLike("%qq%");
      for (Emp emp : emps) {
      System.out.println(emp);
      }
      sqlSession.close();
      }
       

      Opening JDBC Connection
      Created connection 385337537.
      Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@16f7c8c1]
      ==> Preparing: select * from employee where name like "%"?"%";
      ==> Parameters: %qq%(String)
      <== Columns: empid, name, username, password, deptid
      <== Row: 229, qaaqq, 1111, dsa, 2
      <== Row: 231, qqaqq, dsad5, dsa, 7
      <== Total: 2
      emp{empid=229, name='qaaqq', username='1111', pwd='dsa', deptid=2}
      emp{empid=231, name='qqaqq', username='dsad5', pwd='dsa', deptid=7}
      Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@16f7c8c1]
      Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@16f7c8c1]
      Returned connection 385337537 to pool.

       

      log4j:

      1、導(dǎo)入依賴:

       <dependency>
                  <groupId>log4j</groupId>
                  <artifactId>log4j</artifactId>
                  <version>1.2.17</version>
              </dependency>

      2、mybatis-config.xml設(shè)置

         <settings>
              <setting name="logImpl" value="LOG4J"/>
          </settings>

      3、創(chuàng)建log4j.properties文件

      log4j.rootLogger=DEBUG,console,file
      
      #控制臺(tái)輸出的相關(guān)設(shè)置
      log4j.appender.console = org.apache.log4j.ConsoleAppender
      log4j.appender.console.Target = System.out
      log4j.appender.console.Threshold=DEBUG
      log4j.appender.console.layout = org.apache.log4j.PatternLayout
      log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
      
      #文件輸出的相關(guān)設(shè)置
      log4j.appender.file = org.apache.log4j.RollingFileAppender
      log4j.appender.file.File=./log/whily.log
      log4j.appender.file.MaxFileSize=10mb
      log4j.appender.file.Threshold=DEBUG
      log4j.appender.file.layout=org.apache.log4j.PatternLayout
      log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
      
      #日志輸出級(jí)別
      log4j.logger.org.mybatis=DEBUG
      log4j.logger.java.sql=DEBUG
      log4j.logger.java.sql.Statement=DEBUG
      log4j.logger.java.sql.ResultSet=DEBUG
      log4j.logger.java.sql.PreparedStatement=DEBUG

      4、測(cè)試類

      public class EmpDaoTest {
          static Logger logger = Logger.getLogger(EmpDaoTest.class);
      
          @Test
            public void getEmpLike() {
          logger.info("測(cè)試:進(jìn)入getEmpLike方法成功");
      SqlSession sqlSession = MybatisUtils.getSqlSession();
      EmpDao mapper = sqlSession.getMapper(EmpDao.class);

      List<Emp> emps = mapper.getEmpLike("%qq%");
      for (Emp emp : emps) {
      System.out.println(emp);
      }
      logger.info("info:進(jìn)入了testLog4j"); 
      logger.error("error:進(jìn)入了testLog4j");
      logger.debug("debug:進(jìn)入了testLog4j");
          sqlSession.close();
      }
       }

      簡(jiǎn)單使用:

      1.在使用Log4j的類中,導(dǎo)入import org.apache.log4j.Logger;

      2.日志對(duì)象,參數(shù)為當(dāng)前類的class:static Logger logger = Logger.getLogger(EmpDaoTest.class);

      3.日志級(jí)別:

      logger.info("info:進(jìn)入了testLog4j");
      logger.debug("debug:進(jìn)入了testLog4j");
      logger.error("error:進(jìn)入了testLog4j");

      9、分頁(yè)

      分頁(yè)可以減少數(shù)據(jù)的處理量

       

      使用Limit分頁(yè):

      語(yǔ)法:

      select * from tableName limit startIndex,pageSize;

      select * from employee limit 3;   #[0,n]

       9.1:Limit分頁(yè)

       1.接口

      分頁(yè)   List<Emp> getEmpLimit(Map<String,Object> map);

       2.Mapper.xml
      <select id="getEmpLimit" parameterType="map" resultMap="EmpMap">
              select * from employee limit #{i},#{n};
          </select>
       3.測(cè)試 
       @Test
          public void getEmpLimit() {
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              EmpDao mapper = sqlSession.getMapper(EmpDao.class);
              Map<String, Object> map = new HashMap<String, Object>();
              map.put("i", 1);
              map.put("n", 3);
              List<Emp> empLimit = mapper.getEmpLimit(map);
              for (Emp emp:empLimit){
                  System.out.println(emp);
              }
              sqlSession.close();
          }
      
      

      9.2:使用RowBounds(不推薦,因?yàn)樾枰褂胹electList(),官方放棄了這個(gè)方法)

      
      

      1.接口 :List<Emp> getEmpRowBounds();

      
      

      2.Mapper.xml

      <select id="getEmpLimit" parameterType="map" resultMap="EmpMap">
              select * from employee;
          </select>

       

      3.測(cè)試 

      
      
      @Test
      public void getEmpRowBounds(){
      SqlSession sqlSession = MybatisUtils.getSqlSession();
      //RowBounds實(shí)現(xiàn)
      RowBounds rowBounds = new RowBounds(1,3);
      List<Emp> emps = sqlSession.selectList("com.whily.dao.EmpDao.getEmpRowBounds",null,rowBounds);
      for (Emp emp:emps){
      System.out.println(emp);
      }
      sqlSession.close();
      }

      9.3:插件分頁(yè)

      1.到依賴

       

      <dependency>
                  <groupId>com.github.pagehelper</groupId>
                  <artifactId>pagehelper</artifactId>
                  <version>5.1.2</version>
              </dependency>

       

      2.導(dǎo)入插件

      <plugins>
              <plugin interceptor="com.github.pagehelper.PageInterceptor">
                  <property name="helperDialect" value="mysql"/>
                  <property name="reasonable" value="true"/>
              </plugin>
          </plugins>

      3.Dao

      List<Emp> listByHelper();  //條件查詢是需要傳入?yún)?shù)

      4.Mapper.xml

       

      <select id="listByHelper" resultMap="EmpMap">
          select * from employee      
      </select>

      sql語(yǔ)句后面不能加“;”

       

       

      5.測(cè)試

      @Test
          public void ss() {
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              EmpDao mapper = sqlSession.getMapper(EmpDao.class);
      
              PageHelper.startPage(2, 2);
              List<Emp> emps = mapper.listByHelper();
              PageInfo<Emp> info = new PageInfo<Emp>(emps);
              emps = info.getList();
              for (Emp emp : emps) {
                  System.out.println(emp);
              }
          }

      10.注解開發(fā)

       

      修飾在接口方法上,然后加相應(yīng)的sql語(yǔ)句
      
      @Select
                  @Select("select * from emp")
                  public List<Emp> listAnn(Emp emp); 
      @Insert
                  @Insert("insert into emp (ename) values (#{ename})")
      
                  public int saveAnn(Emp emp);
      @Update
                  @Update("update emp set ename=#{ename} where empno=#{empno}")
                  public int editAnn(Emp emp);
      @Delete
                  @Delete("delete from emp  where empno=#{empno}")
                  public int deleteAnn(Emp emp);
      
      @Results
                  @Results(value={
                          @Result(property = "sal", column = "salary")
                  })
                  @Select("select * from emp")
                  public List<Emp> listAnn(Emp emp); 

      #{}和${}:

      where role_id = #{roleId};

      #{}:傳來(lái)參數(shù)時(shí),sql在解析時(shí)會(huì)家伙是哪個(gè)“ ”,當(dāng)成字符串來(lái)解析,防止sql注入。

      ${}:傳入數(shù)據(jù)直接顯示在生成的sql中,解析式就成了role_id = roleId,運(yùn)行時(shí)會(huì)報(bào)錯(cuò)。

      所以盡可能用#{},除非Mybatis排序時(shí)使用order by動(dòng)態(tài)參數(shù)時(shí)需要使用${}而不是#{}

      11、 連表查詢

      一:多對(duì)一映射

      1、創(chuàng)建mybatis-config.xml  實(shí)體類   接口(Dao或Mapper)

      2、Mapeer.xml文件:

             1.方式一,不使用連接查詢,效率一般:

       

          <resultMap id="StudentTeacher" type="stu">
              <result property="stuid" column="stuid" javaType="int"/>
              <result property="stuName" column="stuName" javaType="string"/>
              <association property="teacher" column="tid" javaType="tea" select="getTeacher" //連接第二條查詢語(yǔ)句  >
                  <id property="tchid" column="tchid" javaType="int"></id>
                  <result property="tchName" column="tchName" javaType="string"></result>
              </association>
          </resultMap>
      
          <select id="getStudents" resultMap="StudentTeacher">
              select * from  student
          </select>
      
          <select id="getTeacher" resultType="tea" parameterType="int">
          select  * from teacher where tchid =#{tchid} ;
          </select>

         

        2.方式二,使用連接查詢:

          <select id="getStudents2" resultMap="StudentTeacher2">
              select  s.stuid sid,s.stuName sname,t.tchid tchid,t.tchName tname
              from student s ,teacher t
              where s.tid = t.tchid
          </select>
      
          <resultMap id="StudentTeacher2" type="stu">
              <result property="stuid" column="sid"/>
              <result property="stuName" column="sname"/>
              <association property="teacher" javaType="tea">
                  <id property="tchid" column="tchid"/>
                  <result property="tchName" column="tname"/>
              </association>
          </resultMap>

      二:一對(duì)多映射

       1.方式一,不使用連接查詢:

      <select id="getTeacher2" resultMap="TeacherStu2">
              select  tchid,tchName from teacher where tchid = #{tchid}
          </select>
          <resultMap id="TeacherStu2" type="tea">
              <result property="tchid" column="tchid"/>
              <result property="tchName" column="tchName"/>
              <collection property="students" javaType="ArrayList" ofType="stu" column="tchid"//對(duì)應(yīng)第一條語(yǔ)句的tchid select="getStudentByID"連接第二條語(yǔ)句>
                  <result property="stuid" column="stuid"/>
                  <result property="stuName" column="stuName"/>
                  <result property="tid" column="tid"/>
              </collection>
          <select id="getStudentByID" resultType="stu">
              select stuid,stuName,tid from student where tid = #{tchid}
          </select>
      </resultMap>

        2.方式二,使用連接查詢:

          <select id="getTeacher" resultType="tea" resultMap="TeacherStu">
          select t.tchid ,t.tchName,s.stuid,s.stuName,s.tid from student s,teacher t where s.tid = t.tchid and tchid = #{tchid}
      </select>
          <resultMap id="TeacherStu" type="tea">
              <result property="tchid" column="tchid"/>
              <result property="tchName" column="tchName"/>
              <collection property="students" ofType="stu">
                  <result property="stuid" column="stuid"/>
                  <result property="stuName" column="stuName"/>
                  <result property="tid" column="tid"/>
              </collection>
          </resultMap>

       

      12、動(dòng)態(tài)SQL

      官網(wǎng)描述:
        MyBatis 的強(qiáng)大特性之一便是它的動(dòng)態(tài) SQL。如果你有使用 JDBC 或其它類似框架的經(jīng)驗(yàn),你就能體會(huì)到根據(jù)不同條件拼接 SQL 語(yǔ)句的痛苦。
      例如拼接時(shí)要確保不能忘記添加必要的空格,還要注意去掉列表最后一個(gè)列名的逗號(hào)。利用動(dòng)態(tài) SQL 這一特性可以徹底擺脫這種痛苦。
      雖然在以前使用動(dòng)態(tài) SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射語(yǔ)句中的強(qiáng)大的動(dòng)態(tài) SQL 語(yǔ)言得以改進(jìn)這種情形。
      動(dòng)態(tài) SQL 元素和 JSTL 或基于類似 XML 的文本處理器相似。在 MyBatis 之前的版本中,有很多元素需要花時(shí)間了解。MyBatis 3 大大精簡(jiǎn)了元素種類,
      現(xiàn)在只需學(xué)習(xí)原來(lái)一半的元素便可。MyBatis 采用功能強(qiáng)大的基于 OGNL 的表達(dá)式來(lái)淘汰其它大部分元素。

        -------------------------------
        - if
        - choose (when, otherwise)
        - trim (where, set)
        - foreach
        -------------------------------

      我們之前寫的 SQL 語(yǔ)句都比較簡(jiǎn)單,如果有比較復(fù)雜的業(yè)務(wù),我們需要寫復(fù)雜的 SQL 語(yǔ)句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引號(hào),空格等缺失可能都會(huì)導(dǎo)致錯(cuò)誤。

      那么怎么去解決這個(gè)問題呢?這就要使用 mybatis 動(dòng)態(tài)SQL,通過 if, choose, when, otherwise, trim, where, set, foreach等標(biāo)簽,可組合成非常靈活的SQL語(yǔ)句,從而在提高 SQL 語(yǔ)句的準(zhǔn)確性的同時(shí),也大大提高了開發(fā)人員的效率。

      if:   接口為L(zhǎng)ist<Student> queryStuIf(Map map);

       <select id="queryStuIf" parameterType="map" resultType="stu">
              select * from student where
              <if test="stuid!=null">stuid=#{stuid}</if>
              <if test="stuName!=null">and stuName=#{stuName}</if>
          </select>

      完整語(yǔ)句為select * from student where stuid = #{stuid} and stuName = #{stuName},

      當(dāng)stuName為空時(shí)select * from student where stuid = #{stuid} 

      但當(dāng)stuid為空時(shí)語(yǔ)句就成為了select * from student where and stuName = #{stuName},sql語(yǔ)句錯(cuò)誤。

      如何解決:where

       

      WHERE:接口同上

      修改以上sql語(yǔ)句:

          <select id="queryStuIf" parameterType="map" resultType="stu">
              select * from student where
              <where>
              <if test="stuid!=null">stuid=#{stuid}</if>
              <if test="stuName!=null">and stuName=#{stuName}</if>
              </where>
          </select>
      public void queryOne(){
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
          HashMap<Object,Object> map = new HashMap<Object, Object>();
          map.put("stuid",1);
          map.put("stuName",null);
          List<Student> list = mapper.queryStuIf(map);
          System.out.println(list);
          sqlSession.close();
      }

      這個(gè)“where” 標(biāo)簽會(huì)知道如果他包含的標(biāo)簽中有返回值的話,太插入一個(gè)‘where’。此外,如果標(biāo)簽返回的內(nèi)容是以AND

      或 OR開頭的話,則會(huì)剔除掉。

       

      SET:接口為int update(Map map);

      同理:上面的對(duì)于查詢SQL語(yǔ)句包含where關(guān)鍵字,如果在進(jìn)行更新操作時(shí),含有set關(guān)鍵詞,我們?cè)趺刺幚?/p>

          <update id="update" parameterType="map" >
              update student
              <set>
                  <if test="hobby!=null">hobby=#{hobby},</if>  //注意set與set之間需要加逗號(hào)隔開
                  <if test="stuName">stuName=#{stuName}</if>
              </set>
              where stuid = #{stuid}
          </update>

       public void update(){
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
          HashMap<String,Object> map = new HashMap<String, Object>();
          map.put("stuName","熊大");
          map.put("hobby","dance");
          map.put("stuid",1);
          mapper.update(map);
          sqlSession.commit();
          sqlSession.close();
      }

      CHOOSE語(yǔ)句:List<Student> queryChoose(Map map);

      有時(shí)候我們不想用到所有的查詢條件,只想選擇其中一個(gè),查詢條件只有一個(gè)滿足即可,

      使用choose標(biāo)簽可以解決此類問題,類似于java的switch語(yǔ)句

          <select id="queryChoose" parameterType="map" resultType="stu">
              select * from student
              <where>
                  <choose>
                      <when test="stuid">stuid=#{stuid}</when>
                      <when test="stuName">stuName=#{stuName}</when>
                      <when test="hobby">hobby#{hobby}</when>
                      <otherwise>and view = #{view}</otherwise>
                  </choose>
              </where>
          </select>
          public void queryChoose() {
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
              HashMap<String, Object> map = new HashMap<String, Object>();
              map.put("stuName", "張三");
              //map.put("stuid",1);
              // map.put("hobby","lol");
              // map.put("view",1);
              List<Student> list = mapper.queryChoose(map);
              System.out.println(list);
              sqlSession.close();

       SQL片段:接口List<Student> queryFra(Map map);

      有時(shí)候可能某個(gè)sql語(yǔ)句用的特別多,為了增加代碼的重用性,簡(jiǎn)化代碼,我們需要將這些代碼抽取出來(lái),然后使用時(shí)直接調(diào)用。

          <!--提取片段-->
          <sql id="if-stuid-stuName">
              <if test="stuid!=null">stuid=#{stuid}</if>
              <if test="stuName!=null">stuName=#{stuName}</if>
          </sql>
          
          <!--使用片段-->
          <select id="queryFra" parameterType="map" resultType="stu">
              select * from student
              <where>
              <include refid="if-stuid-stuName"></include>
              </where>
          </select>
       public void queryFra(){
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
          HashMap<String, Object> map = new HashMap<String, Object>();
          //map.put("stuName", "張三");
          map.put("stuid",1);
          List<Student> list=mapper.queryFra(map);
          System.out.println(list);
          sqlSession.close();
      }

      注意:提取片段時(shí),最好基于單表來(lái)定義sql片段,提高片段的可重用性;

         在sql片段中不要包括where

       

      FOREACH:接口List<Student> queryForeach(Map map);

       

      collection:指定輸入對(duì)象中的集合屬性
         item:每次遍歷生成的對(duì)象
         open:開始遍歷時(shí)的拼接字符串
         close:結(jié)束時(shí)拼接的字符串
         separator:遍歷對(duì)象之間需要拼接的字符串
         select * from blog where 1=1 and (id=1 or id=2 or id=3)
       -->
      
          <select id="queryForeach" parameterType="map" resultType="stu">
              select * from student
              <where>
                  <foreach collection="stuids" item="stuid" open="and (" close=")" separator=" or ">stuid=#{stuid}</foreach>//注意空格
              </where>
          </select>
          public void queryForeach(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      
              HashMap map = new HashMap();
              List<Integer> ids = new ArrayList<Integer>();
              ids.add(1);
              ids.add(2);
              ids.add(3);
              map.put("stuids",ids);
              List<Student> students = mapper.queryForeach(map);
              System.out.println(students);
              sqlSession.close();
          }

      13、緩存

      1.什么是緩存:
      • 存在內(nèi)存中的臨時(shí)數(shù)據(jù)。
      • 將用戶經(jīng)常查詢的數(shù)據(jù)放在緩存(內(nèi)存)中,用戶去查詢數(shù)據(jù)就不用從磁盤上(關(guān)系型數(shù)據(jù)庫(kù)數(shù)據(jù)文件)查詢,從緩存中查詢,從而提高查詢效率,解決了高并發(fā)系統(tǒng)的性能問題。
      2.為什么使用緩存:
      • 減少和數(shù)據(jù)庫(kù)的交互次數(shù),減少系統(tǒng)開銷,提高系統(tǒng)效率。
      3.為什么使用緩存:
      • 經(jīng)常查詢并且不經(jīng)常改變的數(shù)據(jù)。

      13.1、Mybatis緩存

      • MyBatis包含一個(gè)非常強(qiáng)大的查詢緩存特性,它可以非常方便地定制和配置緩存。緩存可以極大的提升查詢效率。
      • MyBatis系統(tǒng)中默認(rèn)定義了兩級(jí)緩存:一級(jí)緩存二級(jí)緩存
        •  默認(rèn)情況下,只有一級(jí)緩存開啟。(SqlSession級(jí)別的緩存,也稱為本地緩存)
        •  二級(jí)緩存需要手動(dòng)開啟和配置,他是基于namespace級(jí)別的緩存。
        • 為了提高擴(kuò)展性,MyBatis定義了緩存接口Cache。我們可以通過實(shí)現(xiàn)Cache接口來(lái)自定義二級(jí)緩存

       

      13.1、一級(jí)緩存

      一級(jí)緩存也叫本地緩存:

      • 與數(shù)據(jù)庫(kù)同一次會(huì)話期間查詢到的數(shù)據(jù)會(huì)放在本地緩存中。

      • 以后如果需要獲取相同的數(shù)據(jù),直接從緩存中拿,沒必須再去查詢數(shù)據(jù)庫(kù);

      @org.junit.Test
          public void queryOne(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
             Student i = mapper.queryOne(1);
              System.out.println(i);
              Student j = mapper.queryOne(1);
              System.out.println(j);
              System.out.println(i==j);
              sqlSession.close();
          }


       

       一級(jí)緩存失效的四種情況:

      一級(jí)緩存是SqlSession級(jí)別的緩存,是一直開啟的,我們關(guān)閉不了它;

      一級(jí)緩存失效情況:沒有使用到當(dāng)前的一級(jí)緩存,效果就是,還需要再向數(shù)據(jù)庫(kù)中發(fā)起一次查詢請(qǐng)求!

       

      1.sqlSession不同:

          @org.junit.Test
          public void queryOne(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      SqlSession sqlSession1
      =MybatisUtils.getSqlSession(); StudentMapper mapper1 = sqlSession1.getMapper(StudentMapper.class);
      Student i
      = mapper.queryOne(1); System.out.println(i);
      Student j
      = mapper1.queryOne(1); System.out.println(j); System.out.println(i==j); sqlSession.close(); sqlSession1.close(); }

      觀察結(jié)果:發(fā)現(xiàn)發(fā)送了兩條SQL語(yǔ)句!

      結(jié)論:每個(gè)sqlSession中的緩存相互獨(dú)立


       

      2.sqlSession相同,查詢條件不同

      3.sqlSession相同,兩次查詢之間執(zhí)行了增刪改操作!無(wú)論改的是哪個(gè)對(duì)象,增刪改會(huì)刷新緩存

      4.sqlSession相同,手動(dòng)清除一級(jí)緩存

          @org.junit.Test
          public void queryOne(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
              Student i = mapper.queryOne(1);
              System.out.println(i);
              
              sqlSession.clearCache();//手動(dòng)清除緩存
              Student j = mapper.queryOne(1);
              System.out.println(j);
              System.out.println(i==j);
              sqlSession.close();
          }

      一級(jí)緩存就是一個(gè)map

       

       

      13.2 、二級(jí)緩存

      • 二級(jí)緩存也叫全局緩存,一級(jí)緩存作用域太低了,所以誕生了二級(jí)緩存

      • 基于namespace級(jí)別的緩存,一個(gè)名稱空間,對(duì)應(yīng)一個(gè)二級(jí)緩存;

      • 工作機(jī)制

        • 一個(gè)會(huì)話查詢一條數(shù)據(jù),這個(gè)數(shù)據(jù)就會(huì)被放在當(dāng)前會(huì)話的一級(jí)緩存中;

        • 如果當(dāng)前會(huì)話關(guān)閉了,這個(gè)會(huì)話對(duì)應(yīng)的一級(jí)緩存就沒了;但是我們想要的是,會(huì)話關(guān)閉了,一級(jí)緩存中的數(shù)據(jù)被保存到二級(jí)緩存中;

        • 新的會(huì)話查詢信息,就可以從二級(jí)緩存中獲取內(nèi)容;

        • 不同的mapper查出的數(shù)據(jù)會(huì)放在自己對(duì)應(yīng)的緩存(map)中;

       使用步驟:

      1、開啟全局緩存【mybatis-config.xml】

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

      2、去每個(gè)mapper.xml中配置使用二級(jí)緩存,這個(gè)配置非常簡(jiǎn)單;【xxxMapper.xml】

      <mapper namespace="com.whily.dao.StudentMapper">
      // 在當(dāng)前Mapper.xml中使用二級(jí)緩存
      <cache/> //開啟二級(jí)緩存 <select id="queryOne" resultType="stu"> select * from student where stuid=#{stuid} </select> </mapper>
      <cache/>
      
      官方示例=====>查看官方文檔
      <cache
       eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>
      這個(gè)更高級(jí)的配置創(chuàng)建了一個(gè) FIFO 緩存,每隔 60 秒刷新,最多可以存儲(chǔ)結(jié)果對(duì)象或列表的 512 個(gè)引用,
      而且返回的對(duì)象被認(rèn)為是只讀的,因此對(duì)它們進(jìn)行修改可能會(huì)在不同線程中的調(diào)用者產(chǎn)生沖突

      3.測(cè)試

          @org.junit.Test
          public void queryOne(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              SqlSession sqlSession1 = MybatisUtils.getSqlSession();
              StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
              StudentMapper mapper1 = sqlSession.getMapper(StudentMapper.class);
              Student i = mapper.queryOne(1);
              System.out.println(i);
      
              Student j = mapper1.queryOne(1);
              System.out.println(j);
              System.out.println(i==j);
              sqlSession.close();
              sqlSession1.close();
          }
      org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
      [com.whily.dao.StudentMapper]-Cache Hit Ratio [com.whily.dao.StudentMapper]: 0.0
      [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
      [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 11902257.
      [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@b59d31]
      [com.whily.dao.StudentMapper.queryOne]-==>  Preparing: select * from student where stuid=? 
      [com.whily.dao.StudentMapper.queryOne]-==> Parameters: 1(Integer)
      [com.whily.dao.StudentMapper.queryOne]-<==      Total: 1
      Student{stuid=1, stuName='熊大', hobby=dance, tid=1}
      [com.whily.dao.StudentMapper]-Cache Hit Ratio [com.whily.dao.StudentMapper]: 0.0
      Student{stuid=1, stuName='熊大', hobby=dance, tid=1}
      true

      4.結(jié)論

      • 只要開啟了二級(jí)緩存,我們?cè)谕粋€(gè)Mapper中的查詢,可以在二級(jí)緩存中拿到數(shù)據(jù)

      • 查出的數(shù)據(jù)都會(huì)被默認(rèn)先放在一級(jí)緩存中

      • 只有會(huì)話提交或者關(guān)閉以后,一級(jí)緩存中的數(shù)據(jù)才會(huì)轉(zhuǎn)到二級(jí)緩存中

      5.緩存原理圖

       

       13.3、第三方緩存【EHCache】

      第三方緩存實(shí)現(xiàn)--EhCache: 查看百度百科
      
      Ehcache是一種廣泛使用的java分布式緩存,用于通用緩存;
      
      要在應(yīng)用程序中使用Ehcache,需要引入依賴的jar包
      
      <!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
      <dependency>
         <groupId>org.mybatis.caches</groupId>
         <artifactId>mybatis-ehcache</artifactId>
         <version>1.1.0</version>
      </dependency>
      在mapper.xml中使用對(duì)應(yīng)的緩存即可
      
      <mapper namespace = “org.acme.FooMapper” > 
         <cache type = “org.mybatis.caches.ehcache.EhcacheCache” /> 
      </mapper>
      編寫ehcache.xml文件,如果在加載時(shí)未找到/ehcache.xml資源或出現(xiàn)問題,則將使用默認(rèn)配置。
      <?xml version="1.0" encoding="UTF-8"?>
      <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
              updateCheck="false">
         <!--
            diskStore:為緩存路徑,ehcache分為內(nèi)存和磁盤兩級(jí),此屬性定義磁盤的緩存位置。參數(shù)解釋如下:
            user.home – 用戶主目錄
            user.dir – 用戶當(dāng)前工作目錄
            java.io.tmpdir – 默認(rèn)臨時(shí)文件路徑
          -->
         <diskStore path="./tmpdir/Tmp_EhCache"/>
         
         <defaultCache
                 eternal="false"
                 maxElementsInMemory="10000"
                 overflowToDisk="false"
                 diskPersistent="false"
                 timeToIdleSeconds="1800"
                 timeToLiveSeconds="259200"
                 memoryStoreEvictionPolicy="LRU"/>
      
         <cache
                 name="cloud_user"
                 eternal="false"
                 maxElementsInMemory="5000"
                 overflowToDisk="false"
                 diskPersistent="false"
                 timeToIdleSeconds="1800"
                 timeToLiveSeconds="1800"
                 memoryStoreEvictionPolicy="LRU"/>
         <!--
            defaultCache:默認(rèn)緩存策略,當(dāng)ehcache找不到定義的緩存時(shí),則使用這個(gè)緩存策略。只能定義一個(gè)。
          -->
         <!--
           name:緩存名稱。
           maxElementsInMemory:緩存最大數(shù)目
           maxElementsOnDisk:硬盤最大緩存?zhèn)€數(shù)。
           eternal:對(duì)象是否永久有效,一但設(shè)置了,timeout將不起作用。
           overflowToDisk:是否保存到磁盤,當(dāng)系統(tǒng)當(dāng)機(jī)時(shí)
           timeToIdleSeconds:設(shè)置對(duì)象在失效前的允許閑置時(shí)間(單位:秒)。僅當(dāng)eternal=false對(duì)象不是永久有效時(shí)使用,可選屬性,默認(rèn)值是0,也就是可閑置時(shí)間無(wú)窮大。
           timeToLiveSeconds:設(shè)置對(duì)象在失效前允許存活時(shí)間(單位:秒)。最大時(shí)間介于創(chuàng)建時(shí)間和失效時(shí)間之間。僅當(dāng)eternal=false對(duì)象不是永久有效時(shí)使用,默認(rèn)是0.,也就是對(duì)象存活時(shí)間無(wú)窮大。
           diskPersistent:是否緩存虛擬機(jī)重啟期數(shù)據(jù) Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
           diskSpoolBufferSizeMB:這個(gè)參數(shù)設(shè)置DiskStore(磁盤緩存)的緩存區(qū)大小。默認(rèn)是30MB。每個(gè)Cache都應(yīng)該有自己的一個(gè)緩沖區(qū)。
           diskExpiryThreadIntervalSeconds:磁盤失效線程運(yùn)行時(shí)間間隔,默認(rèn)是120秒。
           memoryStoreEvictionPolicy:當(dāng)達(dá)到maxElementsInMemory限制時(shí),Ehcache將會(huì)根據(jù)指定的策略去清理內(nèi)存。默認(rèn)策略是LRU(最近最少使用)。你可以設(shè)置為FIFO(先進(jìn)先出)或是LFU(較少使用)。
           clearOnFlush:內(nèi)存數(shù)量最大時(shí)是否清除。
           memoryStoreEvictionPolicy:可選策略有:LRU(最近最少使用,默認(rèn)策略)、FIFO(先進(jìn)先出)、LFU(最少訪問次數(shù))。
           FIFO,first in first out,這個(gè)是大家最熟的,先進(jìn)先出。
           LFU, Less Frequently Used,就是上面例子中使用的策略,直白一點(diǎn)就是講一直以來(lái)最少被使用的。如上面所講,緩存的元素有一個(gè)hit屬性,hit值最小的將會(huì)被清出緩存。
           LRU,Least Recently Used,最近最少使用的,緩存的元素有一個(gè)時(shí)間戳,當(dāng)緩存容量滿了,而又需要騰出地方來(lái)緩存新的元素的時(shí)候,那么現(xiàn)有緩存元素中時(shí)間戳離當(dāng)前時(shí)間最遠(yuǎn)的元素將被清出緩存。
        -->
      
      </ehcache>

       

      posted @ 2020-10-20 09:19  whily  閱讀(223)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: а∨天堂一区中文字幕| 精品国产成人国产在线视| 永久无码天堂网小说区| 免费无码成人AV片在线| 18成人片黄网站www| 无码丰满人妻熟妇区| 亚洲av综合色区在线观看| 在线观看亚洲精品国产| 锡林郭勒盟| 亚洲国产一区二区三区久| 动漫av网站免费观看| 四虎国产精品永久在线国在线 | 成人无码区在线观看| 午夜福利激情一区二区三区| 国产成人免费一区二区三区| 久久亚洲精品无码播放| 免费无码影视在线观看mov| 伊人激情一区二区三区av| 97精品伊人久久久大香线蕉 | 亚洲一区二区三级av| 国产免费高清69式视频在线观看| 性XXXX视频播放免费直播| 亚洲婷婷综合色高清在线| 国产熟女丝袜av一二区| 久久天天躁夜夜躁一区| 欧美成人精品手机在线| 97精品人妻系列无码人妻| 无码福利写真片视频在线播放| 特级做a爰片毛片免费看无码| 人人澡人摸人人添| 口爆少妇在线视频免费观看| 欧美熟妇乱子伦XX视频| 在熟睡夫面前侵犯我在线播放| 成人久久精品国产亚洲av| 亚洲一区成人av在线| 国产无遮挡吃胸膜奶免费看| 国产无遮挡又黄又爽不要vip软件| 亚洲情色av一区二区| 久久永久视频| 无码激情亚洲一区| 国产av丝袜熟女一二三|