5.MyBatis

  1. MyBatis简介
  • MyBatis是一个和数据库进行交互的持久化层框架(SQL映射框架);

  • 原始的JDBC

在这里插入图片描述

  • Hibernate-数据库交互的框架(ORM框架) ,相当于一个黑盒子,无需知道里面的细节,但需要多学习HQL语言,且Hibernate是一个全映射框架,部分字段映射很难

在这里插入图片描述

  • MyBatis框架

    在这里插入图片描述

  • MyBatis将重要的步骤抽取出来可以人工定制,其他步骤自动化;
  • 重要步骤都是写在配置文件中(好维护);
  • 完全解决数据库的优化问题;
  • MyBatis底层就是对原生JDBC的一个简单封装;
  • 既将java编码与sql抽取了出来,还不会失去自动化功能;半自动的持久化层框架;
  • mybatis是一个轻量级的框架;
  1. HelloWorld
  • 环境搭建

    • 创建Java工程

    • 创建测试库、测试表、工程中的javabean和操作数据库的dao接口

    • 用MyBatis操作数据库

      • 导包

            //mysql-connector-java-5.1.37-bin.jar
            //mybatis-3.4.1.jar
           //log4j-1.2.17.jar
           //建议导入日志包;这样的化在mybatis关键的环节就会有日志打印;
           //log4j(日志框架);依赖类路径下一个log4j.xml配置文件;
        
      • 写配置

        • 第一个配置文件:(称为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="driver" value="com.mysql.jdbc.Driver"/>
                  <property name="url" value="jdbc:mysql://localhost:3306/mybatis_0325"/>
                  <property name="username" value="root"/>
                  <property name="password" value=""/>
                </dataSource>
              </environment>
            </environments>
            <mappers>
              <mapper resource="org/mybatis/example/BlogMapper.xml"/>
            </mappers>
          </configuration>
          
        • 第二个配置文件:(编写每一个方法都如何向数据库发送sql语句,如何执行,相当于接口的实现类)

          <?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">
          <!--namespce:名称空间,写接口的全类名,相当于告诉Mybatis这个配置文件是来实现哪个接口的  -->
          <mapper namespace="com.atguigu.dao.EmployeeDao">
            <!-- public Employee getEmpById(Integer id); -->
           <!--
           select:用来定义一个查询操作
           id:方法名,相当于这个配置是对于某个方法的实现
           resultType:指定方法运行后的返回值类型;(查询操作必须指定的)
           #{属性名}:代表取出传递过来的某个参数的值
           -->
           <select id="getEmpById" resultType="com.atguigu.bean.Employee">
              select * from t_employee where id=#{id}
            </select>
          </mapper>
          
        • 我们写的dao接口的实现文件,mybatis默认是不知道的,需要在全局配置文件中注册;

            <mappers>
             <!--resource:表示从类路径下找资源  -->
              <mapper resource="EmployeeDao.xml"/>
            </mappers>
          
      • 进行测试

        	@Test
        	public void test() throws IOException {
        		//1.根据全局配置文件创建出一个SqlSessionFactory
        		String resource = "mybatis-config.xml";
        		InputStream inputStream = Resources.getResourceAsStream(resource);
        		//SqlSessionFactory:会话工厂
        		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        		//2.获取和数据库的一次会话,getConnection();
        		SqlSession openSession=sqlSessionFactory.openSession();
        		try {
        
        			//3.使用sqlSession操作数据库,获取到dao接口的实现
        			EmployeeDao employeeDao=openSession.getMapper(EmployeeDao.class);
        			//4.获取到employee对象
        			Employee employee=employeeDao.getEmpById(1);
        			System.out.println(employee);
        		} finally{
        			openSession.close();
        		}
        	}
        
  • 使得写MyBatis有提示

    • 在MyBatis的jar包中解压出这两个文件

      在这里插入图片描述

  • 点击windows->preferences->xml->Catalog

在这里插入图片描述

  • 接下来编写MyBatis的文件就会有提示信息
  1. 增删改查
  • 全局配置文件

    <?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="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis_0325"/>
            <property name="username" value="root"/>
            <property name="password" value=""/>
          </dataSource>
        </environment>
      </environments>
      <mappers>
       <!--resource:表示从类路径下找资源  -->
        <mapper resource="EmployeeDao.xml"/>
      </mappers>
    </configuration>
    
  • 映射文件

    <?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">
    <!--namespce:名称空间,写接口的全类名,相当于告诉Mybatis这个配置文件是来实现哪个接口的  -->
    <mapper namespace="com.atguigu.dao.EmployeeDao">
    <!--	//按照员工id查询员工
    	public Employee getEmpById(Integer id);
    	
    	//更新员工
    	public int updateEmployee(Employee employee);
    	
    	//删除员工
    	public int deleteEmployee(Integer id);
    	
    	//插入员工
    	public int insertEmployee(Employee employee);  -->
     
     <!--public Employee getEmpById(Integer id); 参数类型不用写  -->
     <select id="getEmpById" resultType="com.atguigu.bean.Employee">
        <!--sql语句不要写分号  -->
        select * from t_employee where id=#{id}
      </select>
      
      <!-- public int updateEmployee(Employee employee);
      增删改不用写返回值类型,增删改是返回值影响多少行
      MyBatis自动判断,如果是数字{int,long}
      如果是boolean(影响0行自动封装false,否则true)
      #{属性名},从传入的参数对象中取出对应属性的值
      -->
      <update id="updateEmployee">
      	UPDATE t_employee
    	SET empname=#{empName},gender=#{gender},email=#{email}
    	WHERE id=#{id}
      </update>
      
      <!--public int deleteEmployee(Integer id);  -->
      <delete id="deleteEmployee">
      	DELETE FROM t_employee WHERE id=#{id}
      </delete>
      
      <!--public int insertEmployee(Employee employee)  -->
      <insert id="insertEmployee">
      	INSERT INTO t_employee(empname,gender,email) VALUES(#{empName},#{gender},#{email})
      </insert>
      
      
    </mapper>
    
  • 进行测试

    package com.atguigu.test;
    
    import static org.junit.Assert.*;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    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.Before;
    import org.junit.Test;
    
    import com.atguigu.bean.Employee;
    import com.atguigu.dao.EmployeeDao;
    
    public class MyBatisTest {
    
    	SqlSessionFactory sqlSessionFactory=null;
    	
    	
    	public void init() throws IOException{
    		//1.根据全局配置文件创建出一个SqlSessionFactory
    		String resource = "mybatis-config.xml";
    		InputStream inputStream = Resources.getResourceAsStream(resource);
    		//SqlSessionFactory:会话工厂
    		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    		System.out.println("进行初始化操作");
    	}
    	
    	@Test
    	public void testQuery() throws IOException {
    		//1.根据全局配置文件创建出一个SqlSessionFactory
    		init();
    		//2.获取和数据库的一次会话,getConnection();
    		//openSession设置为true则会自动提交
    		SqlSession openSession=sqlSessionFactory.openSession(true);
    		try {
    
    			//3.使用sqlSession操作数据库,获取到dao接口的实现
    			EmployeeDao employeeDao=openSession.getMapper(EmployeeDao.class);
    			//4.获取到employee对象
    			Employee employee=employeeDao.getEmpById(1);
    			System.out.println(employee);
    		} finally{
    			openSession.close();
    		}
    	}
    	
    	@Test
    	public void testInsert() throws IOException {
    		//1.根据全局配置文件创建出一个SqlSessionFactory
    		init();
    		//2.获取和数据库的一次会话,getConnection();
    		SqlSession openSession=sqlSessionFactory.openSession(true);
    		try {
    			//3.使用sqlSession操作数据库,获取到dao接口的实现
    			EmployeeDao employeeDao=openSession.getMapper(EmployeeDao.class);
    			//4.获取到employee对象
    			int i=employeeDao.insertEmployee(new Employee(null,"tomcat","2200@qq.com",0));
    			System.out.println(i);
    		} finally{
    			openSession.close();
    		}
    	}
    	
    	@Test
    	public void testDelete() throws IOException {
    		//1.根据全局配置文件创建出一个SqlSessionFactory
    		init();
    		//2.获取和数据库的一次会话,getConnection();
    		SqlSession openSession=sqlSessionFactory.openSession(true);
    		try {
    			//3.使用sqlSession操作数据库,获取到dao接口的实现
    			EmployeeDao employeeDao=openSession.getMapper(EmployeeDao.class);
    			//4.获取到employee对象
    			boolean i=employeeDao.deleteEmployee(3);
    			System.out.println(i);
    		} finally{
    			openSession.close();
    		}
    	}
    	
    	@Test
    	public void testUpdate() throws IOException {
    		//1.根据全局配置文件创建出一个SqlSessionFactory
    		init();
    		//2.获取和数据库的一次会话,getConnection();
    		SqlSession openSession=sqlSessionFactory.openSession(true);
    		try {
    			//3.使用sqlSession操作数据库,获取到dao接口的实现
    			EmployeeDao employeeDao=openSession.getMapper(EmployeeDao.class);
    			//4.获取到employee对象
    			int i=employeeDao.updateEmployee(new Employee(1,"tomcat","2200@qq.com",0));
    			System.out.println(i);
    		} finally{
    			openSession.close();
    		}
    	}
    }
    
    
  • 两个文件:

    • 全局配置文件:mybatis-config.xml;指导mybatis正确运行的一些全局设置;
    • SQL映射文件:EmployeeDao.xml;相当于是对Dao接口的一个实现描述
  • 细节

    • 获取到的是接口的代理对象;mybatis自动创建的;
    • SqlSessionFactory创建SqlSession对象,Factory只new一次就行, SqlSession相当于connection和数据库进行交互的,和数据库的一次会话,就应该创建一个新的sqlSession;
  1. 全局配置文件的典型属性
  • properties:properties和spring的context:property-placeholder:一样引用外部配置文件

     	<!--1.properties和spring的context:property-placeholder:一样引用外部配置文件  -->
     	<!--
     		resource:从类路径下开始引用
     		url:引用磁盘路径或者网络路径的资源
     	  -->
     <properties resource="dbconfig.properties"></properties>
     
      <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC"/>
        	<!--配置连接池  -->
          <dataSource type="POOLED">
            <property name="driver" value="${driverclass}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          </dataSource>
        </environment>
      </environments>
    
  • settings修改mybatis运行时的行为

     <!--2.这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。  -->
     <settings>
     	<!--name,配置项的key,value,配置项的值  -->
     	<!--开启驼峰命名  -->
     	<setting name="mapUnderscoreToCamelCase" value="true"/>
     </settings>
    

    其他设置

    设置名描述有效值默认值
    cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | falsetrue
    lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
    aggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默认为 true)
    multipleResultSetsEnabled是否允许单个语句返回多结果集(需要数据库驱动支持)。true | falsetrue
    useColumnLabel使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。true | falsetrue
    useGeneratedKeys允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。true | falseFalse
    autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
    autoMappingUnknownColumnBehavior指定发现自动映射目标未知列(或未知属性类型)的行为。NONE: 不做任何反应WARNING: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARNFAILING: 映射失败 (抛出 SqlSessionException)NONE, WARNING, FAILINGNONE
    defaultExecutorType配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。SIMPLE REUSE BATCHSIMPLE
    defaultStatementTimeout设置超时时间,它决定数据库驱动等待数据库响应的秒数。任意正整数未设置 (null)
    defaultFetchSize为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。任意正整数未设置 (null)
    defaultResultSetType指定语句默认的滚动策略。(新增于 3.5.2)FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置)未设置 (null)
    safeRowBoundsEnabled是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。true | falseFalse
    safeResultHandlerEnabled是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。true | falseTrue
    mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。true | falseFalse
    localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。SESSION | STATEMENTSESSION
    jdbcTypeForNull当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。OTHER
    lazyLoadTriggerMethods指定对象的哪些方法触发一次延迟加载。用逗号分隔的方法列表。equals,clone,hashCode,toString
    defaultScriptingLanguage指定动态 SQL 生成使用的默认脚本语言。一个类型别名或全限定类名。org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
    defaultEnumTypeHandler指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5)一个类型别名或全限定类名。org.apache.ibatis.type.EnumTypeHandler
    callSettersOnNulls指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。true | falsefalse
    returnInstanceForEmptyRow当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2)true | falsefalse
    logPrefix指定 MyBatis 增加到日志名称的前缀。任何字符串未设置
    logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
    proxyFactory指定 Mybatis 创建可延迟加载对象所用到的代理工具。CGLIB | JAVASSISTJAVASSIST (MyBatis 3.3 以上)
    vfsImpl指定 VFS 的实现自定义 VFS 的实现的类全限定名,以逗号分隔。未设置
    useActualParamName允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1)true | falsetrue
    configurationFactory指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3)一个类型别名或完全限定类名。未设置
    shrinkWhitespacesInSqlRemoves extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. (Since 3.5.5)true | falsefalse

    完整配置

    <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>
    
  • typeAliases为类起别名

     <!--3.类型别名typeAliases  -->
     <typeAliases>
     	<!--typeAlias就是为一个javaBean起别名,别名默认就是类名(不区分大小写),配置文件中就写类名 
     	 -->
     	 <typeAlias type="com.atguigu.bean.Employee" alias="Employee"/>
     	 <!--批量起别名 name=""指定包名,默认别名就是类名 -->
     	 <package name="com.atguigu.bean"/>
     	 <!--推荐使用全类名  -->
     </typeAliases>
    
    @Alias("emp")//为该类起另外别名,配置文件里的就失效了
    public class Employee {
    
    	private Integer id;
    	private String empName;
    	private String email;
    	private Integer gender;
    	private String loginAccount;
    

    下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

    别名映射的类型
    _bytebyte
    _longlong
    _shortshort
    _intint
    _integerint
    _doubledouble
    _floatfloat
    _booleanboolean
    stringString
    byteByte
    longLong
    shortShort
    intInteger
    integerInteger
    doubleDouble
    floatFloat
    booleanBoolean
    dateDate
    decimalBigDecimal
    bigdecimalBigDecimal
    objectObject
    mapMap
    hashmapHashMap
    listList
    arraylistArrayList
    collectionCollection
    iteratorIterator
  • 类型处理器 typeHandlers

     <typeHandlers>
     	<!--自定义好的类型处理器这么配置上就行了  -->
     	<typeHandler handler=""/>
     </typeHandlers>
    
  • plugins插件

    plugins插件是MyBatis中强大的机制

  • environments

     <!--6.environments配置环境们
       environment:配置一个具体的环境,都需要一个事务管理器和一个数据源
       id:是当前环境的唯一表示
       default:默认使用哪个环境
       transactionManager:事务管理器 
       dataSource:数据源
          后来的数据源和事务管理器都是Spring来做-->
     
      <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC"/>
        	<!--配置连接池  -->
          <dataSource type="POOLED">
            <property name="driver" value="${driverclass}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          </dataSource>
        </environment>
      </environments>
    
  • databaseIdProvider:mybatis用来数据库移植的

      <!--6.databaseIdProvider:mybatis用来数据库移植的  -->
    	<databaseIdProvider type="DB_VENDOR">
    	 <!--name="",数据库厂商标识,value,给这个标识起一个好用的名字	-->
    	  <property name="MySQL" value="mysql"/>
    	  <property name="SQL Server" value="sqlserver"/>
    	  <property name="DB2" value="db2"/>
    	  <property name="Oracle" value="oracle" />
    	</databaseIdProvider>
    

    映射文件

     <!--如果能精确匹配就精确匹配,不能就模糊匹配  -->
     <select id="getEmpById" resultType="com.atguigu.bean.Employee" databaseId="mysql">
        <!--sql语句不要写分号  -->
        select * from t_employee where id=#{id}
      </select>
    
     <select id="getEmpById" resultType="com.atguigu.bean.Employee" databaseId="oracle">
        <!--sql语句不要写分号  -->
        <!--oracle语句-->
      </select>
    
     <select id="getEmpById" resultType="com.atguigu.bean.Employee" databaseId="db2">
        <!--sql语句不要写分号  -->
         <!--db2语句-->
      </select>
    
  • mappers:写好的sql映射文件需要使用mapper注册进来

    	<!--7.写好的sql映射文件需要使用mapper注册进来  -->
      <mappers>
       <!--
       resource:表示从类路径下找资源 
       class:直接引用接口的全类名
       		可以将xml放在和dao接口通目录下,而且文件名和接口名一致
       url:可以从网络或者磁盘路径中引用
        -->
        <mapper resource="EmployeeDao.xml"/> 
        <!--注解方式  -->
        <mapper class="com.atguigu.dao.EmployeeDaoAnno"/>
        <!--resource、class两种方式可以配合使用,重要的dao写在配置中,不重要的可以写注解  -->
        <!--批量注册  -->
        <package name="com.atguigu.dao"/>
      </mappers>
    

    注解java

    public interface EmployeeDaoAnno {
    	
    	//按照员工id查询员工
    	@Select("select * from t_employee where id=#{id}")
    	public Employee getEmpById(Integer id);
    	
    	//更新员工
    	@Update("UPDATE t_employee SET empname=#{empName},gender=#{gender},email=#{email} WHERE id=#{id}")
    	public int updateEmployee(Employee employee);
    	
    	//删除员工
    	@Delete("DELETE FROM t_employee WHERE id=#{id}")
    	public boolean deleteEmployee(Integer id);
    	
    	//插入员工
    	@Insert("INSERT INTO t_employee(empname,gender,email) VALUES(#{empName},#{gender},#{email})")
    	public int insertEmployee(Employee employee);
    }
    
    
  1. SQL映射文件
  • 增删改属性

在这里插入图片描述

  • 主键自增

     <!--让MyBatis自动的将自增id赋值传入的employee对象的id属性
         useGeneratedKeys="true",原生的jdbc获取自增主键的方法
         keyProperty="",将刚才自增的id封装给哪个属性
         -->
      <insert id="insertEmployee" useGeneratedKeys="true" keyProperty="id">
      	INSERT INTO t_employee(empname,gender,email) VALUES(#{empName},#{gender},#{email})
      </insert>
    
  • 非主键自增的

     <insert id="insertEmployee">
      	<!--order="BEFORE"表示执行下面sql语句之前执行里面sql语句,AFTER表示在之后
      	之后会将id值赋给插入的javaBean的对象  -->
      	<selectKey order="BEFORE" resultType="Integer" keyProperty="id">
      		select max(id) from t_employee
      	</selectKey>
      	INSERT INTO t_employee(empname,gender,email) VALUES(#{empName},#{gender},#{email})
      </insert>
    
  • 查询属性

    • 单个参数:基本类型取值:#{随便写},POJO则是#{属性名}

    • 多个参数:

      			public Employee getEmpByIdAndEmpName(Integer id,String empName)
      			取值:#{参数名}是无效了;
      			可用:0,1(参数的索引)或者param1,param2(第几个参数paramN)
      			原因:只要传入了多个参数;mybatis会自动的将这些参数封装在一个map中;
      				封装时使用的key就是参数的索引和参数的第几个表示
      				Map<String,Object> map = new HashMap<>();
      				map.put("1",传入的值);map.put("2","传入的值");
      			#{key}就是从这个map中取值;
      
    • 3)、@Param:为参数指定key;该注解是加在接口对应方法的参数前面的,我们以后也推荐这么做;
      我们可以告诉mybatis,封装参数map的时候别乱来,使用我们指定的key

    • 传入了pojo(javaBean):取值:#{pojo的属性名}

    • 传入了map:将多个要使用的参数封装起来,取值:#{key}

  • #{key/属性名}

    • #{key}取值的时候可以设置一些规则:如id=#{id,jdbcType=INT};

      • 规则:javaType、jdbcType、mode、numericScale、resultMap、typeHandler、jdbcTypeName、expression
      • 只有jdbcType才可能是需要被指定的;默认不指定jdbcType;mysql没问题;oracle没问题;万一传入的数据是null;mysql插入null没问题,oracle会出现问题【oracle不知道null到底是什么类型;】
    • 实际上在mybatis中:两种取值方式:#{属性名}和${属性名}

      • #{属性名}:是参数预编译的方式,参数的位置都是用?替代,参数后来都是预编译设置进去的;安全,不会有sql注入问题

        id=#{id} and empname=#{empName}:
        		select * from t_employee where id=? and empname=? 
        
      • ${属性名}:不是参数预编译,而是直接和sql语句进行拼串;不安全;

        id=${id} and empname=#{empName}:
        		select * from t_employee where id=1 and empname=? 
        
      • sql语句只有参数位置是支持预编译的,而表位置是不支持预编译的,当需要动态传表名时,表明位置就可以用${},

      • 一般都是使用#{};安全;在不支持参数预编译的位置要进行取值就使用${};

  • 查询结果返回list

    • <!-- public List<Employee> getAllEmps(); -->
       	  <!-- resultType="":如果返回的是集合,写的是集合里面元素的类型 -->
       	  <select id="getAllEmps" resultType="com.atguigu.bean.Employee">
       	  		select * from t_employee
       	  </select>
      
    • @Test
       	public void testGetAllEmps() throws IOException {
       		//1.根据全局配置文件创建出一个SqlSessionFactory
       		init();
       		//2.获取和数据库的一次会话,getConnection();
       		SqlSession openSession=sqlSessionFactory.openSession(true);
       		try {
       			//3.使用sqlSession操作数据库,获取到dao接口的实现
       			EmployeeDao employeeDao=openSession.getMapper(EmployeeDao.class);
       			//4.获取到employee数组对象
       			List<Employee> list=employeeDao.getAllEmps();
       			System.out.println(list);
       		} finally{
       			openSession.close();
       		}
       	}
      
  • 查询结果返回Map

    • <!--public Map<String,Object> getEmpByIdReturnMap(Integer id);  -->
         	  <select id="getEmpByIdReturnMap" resultType="map">
         	  	select * from t_employee where id=#{id}
         	  </select>
      
    • @Test
       	public void testReturnMap() throws IOException {
       		//1.根据全局配置文件创建出一个SqlSessionFactory
       		init();
       		//2.获取和数据库的一次会话,getConnection();
       		SqlSession openSession=sqlSessionFactory.openSession(true);
       		try {
       			//3.使用sqlSession操作数据库,获取到dao接口的实现
       			EmployeeDao employeeDao=openSession.getMapper(EmployeeDao.class);
       			//4.获取到employee数组对象
       			Map<String,Object> map=employeeDao.getEmpByIdReturnMap(1);
       			System.out.println(map);
       		} finally{
       			openSession.close();
       		}
       	}
      
  • 查询结果返回多个对象的

    • 	  	<!-- public Map<Integer,Employee> getEmpsReturnMap(); -->
      	  	<!--注意,返回结果的是集合的,需要将resultType设置为集合中的类型  -->
      	  <select id="getEmpsReturnMap" resultType="Employee">
      	  	select * from t_employee
      	  </select>
      
    • //返回的是所有Employee的Map集合
      //@MapKey标注查出来的数据哪个属性作为map的key	
      @MapKey("id")
      	public Map<Integer,Employee> getEmpsReturnMap();
      
    • @Test
       	public void testReturnMaps() throws IOException {
       		//1.根据全局配置文件创建出一个SqlSessionFactory
       		init();
       		//2.获取和数据库的一次会话,getConnection();
       		SqlSession openSession=sqlSessionFactory.openSession(true);
       		try {
       			//3.使用sqlSession操作数据库,获取到dao接口的实现
       			EmployeeDao employeeDao=openSession.getMapper(EmployeeDao.class);
       			//4.获取到employee数组对象
       			Map<Integer,Employee> map=employeeDao.getEmpsReturnMap();
       			System.out.println(map);
       		} finally{
       			openSession.close();
       		}
       	}
      
  • resultMap自定义封装规则

    • CatDao.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.atguigu.dao.CatDao">
      	<!-- getCatById(Integer) 
      	resultType="com.atguigu.bean.Cat":使用默认规则;属性列名一一对应
      	resultMap="mycat":查出数据封装结果的时候,使用mycat自定义的规则
      	-->
      	<select id="getCatById" resultMap="mycat">
      		select *  from t_cat where id=#{id}
      	</select>
      	
      	
      	<!-- 自定义结果集(resultMap):自己定义每一列数据和javaBean的映射规则
      	type="":指定为哪个javaBean自定义封装规则;全类名
      	id="":唯一标识;让别名在后面引用
      	
      	    id  cName     cAge  cgender  
              1    加菲猫            12          0
      	 -->
      	<resultMap type="com.atguigu.bean.Cat" id="mycat">
      		<!-- 指定主键列的对应规则;
      		column="id":指定哪一列是主键列
      		property="":指定cat的哪个属性封装id这一列数据
      		 -->
      		<id property="id" column="id"/>
      		<!-- 普通列 -->
      		<result property="name" column="cName"/>
      		<result property="age" column="cAge"/>
      		<result property="gender" column="cgender"/>
      	</resultMap>
      </mapper>
      
    • CatDao.java

      public interface CatDao {
      	
      	public Cat getCatById(Integer id);
      
      }
      
    • Cat.java

      package com.atguigu.bean;
      
      public class Cat {
      	
      	private Integer id;
      	private String name;
      	private Integer gender;
      	private Integer age;
      	/**
      	 * @return the id
      	 */
      	public Integer getId() {
      		return id;
      	}
      	/**
      	 * @param id the id to set
      	 */
      	public void setId(Integer id) {
      		this.id = id;
      	}
      	/**
      	 * @return the name
      	 */
      	public String getName() {
      		return name;
      	}
      	/**
      	 * @param name the name to set
      	 */
      	public void setName(String name) {
      		this.name = name;
      	}
      	/**
      	 * @return the gender
      	 */
      	public Integer getGender() {
      		return gender;
      	}
      	/**
      	 * @param gender the gender to set
      	 */
      	public void setGender(Integer gender) {
      		this.gender = gender;
      	}
      	/**
      	 * @return the age
      	 */
      	public Integer getAge() {
      		return age;
      	}
      	/**
      	 * @param age the age to set
      	 */
      	public void setAge(Integer age) {
      		this.age = age;
      	}
      	/* (non-Javadoc)
      	 * @see java.lang.Object#toString()
      	 */
      	@Override
      	public String toString() {
      		return "Cat [id=" + id + ", name=" + name + ", gender=" + gender
      				+ ", age=" + age + "]";
      	}
      }
      
      
    • Test.java

      /**
      	 * 默认mybatis自动封装结果集;
      	 * 1)、按照列名和属性名一一对应的规则(不区分大小写);
      	 * 2)、如果不一一对应;
      	 * 		1)、开启驼峰命名法(满足驼峰命名规则  aaa_bbb  aaaBbb)
      	 * 		2)、起别名:
      	 */
      	@Test
      	public void test04() {
      		SqlSession openSession = sqlSessionFactory.openSession();
      		try {
      			CatDao mapper = openSession.getMapper(CatDao.class);
      			Cat catById = mapper.getCatById(1);
      			System.out.println(catById);
      			
      		} finally {
      			openSession.close();
      		}
      	}
      
  • 联合查询

    • 使用级联属性封装联合查询后的所有结果

      • Key.java

        public class Key {
        	private int id;
        	private String keyName;
        	private Lock lock;
        }
        
      • Lock.java

        public class Lock {	
        	private int id;
        	private String lockName;
        }
        
      • KeyDao.java

        public interface KeyDao {
        	
        	public Key getKeyById(Integer id);
        }
        
      • KeyDao.xml

        	<!-- getKeyById(Integer) -->
         	<!-- 
        	 	private Integer id;//钥匙的id
        		private String keyName;//钥匙的名
        		private Lock lock;//当前钥匙能开哪个锁;
        		
        		id  keyname     lockid     lid  lockName  
         	 -->
         	<select id="getKeyById" resultMap="mykey">
         		select k.id,k.`keyname`,k.`lockid`,
        		       l.`id` lid,l.`lockName` from t_key k
        			left join t_lock l on k.`lockid`=l.`id`
        			where k.`id`=#{id}
         	</select>
         	
         	<!-- 自定义封装规则:使用级联属性封装联合查询出的结果 -->
        <resultMap type="com.atguigu.bean.Key" id="mykey">
         		<id property="id" column="id"/>
         		<result property="keyName" column="keyname"/>
         		<result property="lock.id" column="lid"/>
         		<result property="lock.lockName" column="lockName"/>
         	</resultMap>
        
      • MyBatis推荐的方式

         	<!-- mybatis推荐的   <association property=""></association>-->
         	<resultMap type="com.atguigu.bean.Key" id="mykey">
         		<id property="id" column="id"/>
         		<result property="keyName" column="keyname"/>
         		<!-- 接下来的属性是一个对象,自定义这个对象的封装规则;使用association;表示联合了一个对象 -->
         		<!-- javaType:指定这个属性的类型 -->
         		<association property="lock" javaType="com.atguigu.bean.Lock">
         			<!-- 定义lock属性对应的这个Lock对象如何封装 -->
         			<id property="id" column="lid"/>
         			<result property="lockName" column="lockName"/>
         		</association>
         	</resultMap>
        
    • collection定义集合封装类型

      • <?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.atguigu.dao.LockDao">
          	
         	<!-- public Lock getLockById(Integer id); -->
         	<select id="getLockById" resultMap="mylock">
         		select l.*,k.id kid,k.`keyname`,k.`lockid` from t_lock l 
        			left join t_key k on l.`id`=k.`lockid`
        			where l.id=#{id}
         	</select>
         	
         	<!--
        	 	private Integer id;
        		private String lockName;
        		//查询锁子的时候把所有的钥匙也查出来
        		private List<Key> keys;
        		
        		id  lockName                  kid  keyname     lockid  
        		3  303办公室的锁子                   			3  303钥匙1           3
             	3  303办公室的锁子                  			4  303钥匙2           3
             	3  303办公室的锁子                   			5  303钥匙3           3
         	  -->
         	<resultMap type="com.atguigu.bean.Lock" id="mylock">
         		<id property="id" column="id"/>
         		<result property="lockName" column="lockName"/>
         		<!-- 
         		collection:定义集合元素的封装 
         			property="":指定哪个属性是集合属性
         			javaType:指定对象类型;association
         			ofType="":指定集合里面元素的类型
         		-->
         		<collection property="keys" ofType="com.atguigu.bean.Key">
         			<!-- 标签体中指定集合中这个元素的封装规则 -->
         			<id property="id" column="kid"/>
         			<result property="keyName" column="keyname"/>
         		</collection>
         	</resultMap>
          </mapper>
        
      • public interface LockDao {
        	
        	//查锁子的时候将所有钥匙也查出来
        	public Lock getLockById(Integer id);
        	
        }
        
      • @Test
         	public void testLockDao() throws IOException {
         		//1.根据全局配置文件创建出一个SqlSessionFactory
         		init();
         		//2.获取和数据库的一次会话,getConnection();
         		SqlSession openSession=sqlSessionFactory.openSession(true);
         		try {
         			//3.使用sqlSession操作数据库,获取到dao接口的实现
         			LockDao lockDao=openSession.getMapper(LockDao.class);
         			Lock lock=lockDao.getLockById(3);
         			System.out.println(lock);
         		} finally{
         			openSession.close();
         		}
         	}
        
    • 使用select实现分布查询

      • <select id="getKeyByIdSimple" resultMap="mykey02">
          		select * from t_key where id=#{id}
          	</select>
          	<resultMap type="com.atguigu.bean.Key" id="mykey02">
          		<id property="id" column="id"/>
          		<result property="keyName" column="keyname"/>
          		<!--告诉mybatis自己去调用一个查询查锁子
          		select="":指定一个查询sql的唯一标识;mybatis自动调用指定的sql将查出的lock封装进来
          		public Lock getLockByIdSimple(Integer id);需要传入锁子id
          		告诉mybatis把哪一列的值传递过去
          		column:指定将哪一列的数据传递过去
          		  -->
          		<association property="lock" 
          			select="LockDao.getLockById"
          			column="lockid" fetchType="lazy"></association>
          	</resultMap>
        
      • @Test
         	public void testKeyDaoSelect() throws IOException {
         		//1.根据全局配置文件创建出一个SqlSessionFactory
         		init();
         		//2.获取和数据库的一次会话,getConnection();
         		SqlSession openSession=sqlSessionFactory.openSession(true);
         		try {
         			//3.使用sqlSession操作数据库,获取到dao接口的实现
         			KeyDao keyDao=openSession.getMapper(KeyDao.class);
         			Key key=keyDao.getKeyByIdSimple(1);
         			System.out.println();
         		} finally{
         			openSession.close();
         		}
         	}
        
      • 如果要按需加载和延迟加载

         	<settings>
        		<!-- 开启延迟加载开关 -->
        		<setting name="lazyLoadingEnabled" value="true"/>
        		<!-- 开启属性按需加载 -->
        		<setting name="aggressiveLazyLoading" value="false"/>
        	</settings>
        
  • 动态sql

    • if判断与trim

      	<!-- if:判断 -->
      	<!--public List<Teacher> getTeacherByCondition(Teacher teacher); -->
      	<select id="getTeacherByCondition" resultMap="teacherMap">
      		select * from t_teacher
      		<!-- test="":编写判断条件 id!=null:取出传入的javaBean属性中的id的值,判断其是否为空 -->
      		<!-- where可以帮我们去除掉前面的and; -->
      
      		<!-- trim:截取字符串 
      			prefix="":前缀;为我们下面的sql整体添加一个前缀 
      			prefixOverrides="": 取出整体字符串前面多余的字符 
      			suffix="":为整体添加一个后缀 
      			suffixOverrides="":后面哪个多了可以去掉; -->
      		<!-- 我们的查询条件就放在where标签中;每个and写在前面,
      			where帮我们自动取出前面多余的and -->
      		<trim prefix="where" prefixOverrides="and" suffixOverrides="and">
      			<if test="id!=null">
      				id > #{id} and
      			</if>
      			<!-- 空串 "" and; && or: ||; if():传入非常强大的判断条件;
      			方法、静态方法、构造器。xxx
      			在mybatis中,传入的参数可以用来做判断;
      			额外还有两个东西;
      			_parameter:代表传入来的参数;
      				1)、传入了单个参数:_parameter就代表这个参数
      				2)、传入了多个参数:_parameter就代表多个参数集合起来的map
      			_databaseId:代表当前环境
      				如果配置了databaseIdProvider:_databaseId就有值
      				
      			 -->
      			<if test="name!=null &amp;&amp; !name.equals(&quot;&quot;)">
      				teacherName like #{name} and
      			</if>
      			<if test="birth!=null">
      				birth_date &lt; #{birth} and
      			</if>
      		</trim>
      	</select>
      
    • OGNL对象导航图语言

      			OGNL表达式;对象导航图语言
      				Person
      					===lastName
      					===email
      					===Address
      						===city
      						===province
      						===Street
      							===adminName
      							===info
      							===perCount
      
    • foreach

      <!-- public List<Teacher> getTeacherByIdIn(List<Integer> ids); -->
      	<select id="getTeacherByIdIn" resultMap="teacherMap">
      		
      		SELECT * FROM t_teacher WHERE id IN
      		<!-- 帮我们遍历集合的; collection="":指定要遍历的集合的key 
      		close="":以什么结束 
      		index="i":索引; 
      			如果遍历的是一个list; 
      				index:指定的变量保存了当前索引 
      				item:保存当前遍历的元素的值 
      			如果遍历的是一个map: 
      				index:指定的变量就是保存了当前遍历的元素的key 
      				item:就是保存当前遍历的元素的值
      		item="变量名":每次遍历出的元素起一个变量名方便引用 
      		open="":以什么开始 
      		separator="":每次遍历的元素的分隔符 
      			(#{id_item},#{id_item},#{id_item} -->
      		<if test="ids.size >0">
      			<foreach collection="ids" item="id_item" separator="," open="("
      				close=")">
      				#{id_item}
      			</foreach>
      		</if>
      	</select>
      
    • choose选择

       <!--if与when的区别:if是每个条件都会执行一遍,而when则按顺序只执行第一个满足的条件  -->
      	<!--public List<Teacher> getTeacherByConditionChoose(Teacher teacher); -->
      	<select id="getTeacherByConditionChoose" resultMap="teacherMap">
      		select * from t_teacher
      		<where>
      			<choose>
      				<when test="id!=null">
      					id=#{id}
      				</when>
      				<when test="name!=null and !name.equals(&quot;&quot;)">
      					teacherName=#{name}
      				</when>
      				<when test="birth!=null">
      					birth_date = #{birth}
      				</when>
      				<otherwise>
      					1=1
      				</otherwise>
      			</choose>
      		</where>
      	</select>
      
    • update中的set

      	<!-- public int updateTeacher(Teacher teacher); -->
      	<update id="updateTeacher">
      		UPDATE t_teacher
      		<set>
      			<if test="name!=null and !name.equals(&quot;&quot;)">
      				teacherName=#{name},
      			</if>
      			<if test="course!=null and !course.equals(&quot;&quot;)">
      				class_name=#{course},
      			</if>
      			<if test="address!=null and !address.equals(&quot;&quot;)">
      				address=#{address},
      			</if>
      			<if test="birth!=null">
      				birth_date=#{birth}
      			</if>
      		</set>
      		<where>
      			id=#{id}
      		</where>
      	</update>
      
    • 抽取sql

      	<!--抽取可重用的sql语句  -->
      	<sql id="selectSql">select * from t_teacher</sql>
      	<!--public Teacher getTeacherById(Integer id); -->
      	<select id="getTeacherById" resultMap="teacherMap">
      		<include refid="selectSql"></include>
      		where id=#{id}
      	</select>
      
  1. 缓存
  • 暂时的存储一些数据;加快系统的查询速度…

  • 一级缓存:是线程级别的缓存,本地缓存,SqlSession级别的缓存,默认是存在的;

    • 机制:只要之前查询过的数据,mybatis就会保存在一个缓存中(Map);下次获取直接从缓存中拿;

    • 一级缓存失效的几种情况:

      • 不同的SqlSession对应不同的一级缓存

      • 同一个SqlSession但是查询条件不同

      • 同一个SqlSession两次查询期间执行了任何一次增删改操作

      • 同一个SqlSession两次查询期间手动清空了缓存

      • 会生成一个很长的key

        在这里插入图片描述

  • 二级缓存:全局范围的缓存,除过当前线程,SqlSession能用外其他也可以使用,一般缓存的bean要实现序列化接口;namespace级别的缓存;

    • 全局配置开启二级缓存

      <!-- 开启全局缓存开关; -->
              <setting name="cacheEnabled" value="true"/>
      
    • 配置某个dao.xml文件,让其使用二级缓存

      <cache></cache>
      
  • 缓存的原理

    • 缓存的原理图

      在这里插入图片描述

  • 缓存的顺序(可参照原理图)

    • 不会出现一级缓存和二级缓存中有同一个数据,在二级缓存中,一级缓存关闭了就有了;一级缓存中:二级缓存中没有此数据,就会看一级缓存,一级缓存没有去查数据库;数据库的查询后的结果放在一级缓存中了;
    • 任何时候都是先看二级缓存、再看一级缓存,如果大家都没有就去查询数据库;
    • 查询顺序可简单理解为:二级缓存-》一级缓存-》数据库
  • 缓存的配置

    • 全局setting的cacheEnable:配置二级缓存的开关。一级缓存一直是打开的。
    • select标签的useCache属性:配置这个select是否使用二级缓存。一级缓存一直是使用的
    • sql标签的flushCache属性:增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。查询默认flushCache=false。
    • sqlSession.clearCache():只是用来清除一级缓存。
    • 当在某一个作用域 (一级缓存Session/二级缓存Namespaces) 进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
  • 整合第三方缓存包的顺序

    • 导入第三方包

      ehcache-core-2.6.8.jar(ehcache核心包)
      mybatis-ehcache-1.0.3.jar(ehcache的整合包) 
      slf4j-api-1.7.21.jar
      slf4j-log4j12-1.7.21.jar
      
    • ehcache要工作有一个配置文件;

      在mapper.xml中配置使用自定义的缓存<?xml version="1.0" encoding="UTF-8"?>
      <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
       <!-- 磁盘保存路径 -->
       <diskStore path="D:\44\ehcache" />
       <defaultCache 
         maxElementsInMemory="1" 
         maxElementsOnDisk="10000000"
         eternal="false" 
         overflowToDisk="true" 
         timeToIdleSeconds="120"
         timeToLiveSeconds="120" 
         diskExpiryThreadIntervalSeconds="120"
         memoryStoreEvictionPolicy="LRU">
       </defaultCache>
      </ehcache>
       
      <!-- 
      属性说明:
      l diskStore:指定数据在磁盘中的存储位置。
      l defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
       
      以下属性是必须的:
      l maxElementsInMemory - 在内存中缓存的element的最大数目 
      l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
      l eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
      l overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
       
      以下属性是可选的:
      l timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
      l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
       diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
      l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
      l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
      l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
       -->
      
    • 在mapper.xml中配置使用自定义的缓存

      <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
      
    • 别的dao还要用这个缓存,缓存引用cache-ref

      <!--  和别的dao共用一块缓存-->
          <cache-ref namespace="com.atguigu.dao.TeacherDao"/>
      
  1. MBG逆向工程
  • 逆向工程:根据数据表table,逆向分析数据表,自动生成javaBean—BookDao—dao.xml—xxx

  • MBG:MyBatis Generator:代码生成器;MyBatis官方提供的代码生成器;帮我们逆向生成;

  • 使用步骤

    • 导包:mbg的核心包

    • 编写mbg.xml配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
      
      <generatorConfiguration>
      
          <!--
          MyBatis3Simple:基础班CRUD
          MyBatis3:复杂版CRUD
           -->
          <context id="DB2Tables" targetRuntime="MyBatis3">
              <commentGenerator>
                  <property name="suppressAllComments" value="true"/>
              </commentGenerator>
              <!-- jdbcConnection:指导连接到哪个数据库 -->
              <jdbcConnection
      
                  driverClass="com.mysql.jdbc.Driver"
                  connectionURL="jdbc:mysql://localhost:3306/mybatis_0325"
      
                  userId="root"
      
                  password="123456">
              </jdbcConnection>
      
              <javaTypeResolver>
                  <property name="forceBigDecimals" value="false" />
              </javaTypeResolver>
      
              <!-- javaModelGenerator:生成pojo
      
              targetPackage:生成的pojo放在哪个包
              targetProject:放在哪个工程下
              -->
              <javaModelGenerator targetPackage="com.atguigu.bean"
                  targetProject=".\src">
                  <property name="enableSubPackages" value="true" />
                  <property name="trimStrings" value="true" />
              </javaModelGenerator>
      
              <!--sqlMapGenerator:sql映射文件生成器;指定xml生成的地方  -->
              <sqlMapGenerator targetPackage="com.atguigu.dao"
                  targetProject=".\conf">
                  <property name="enableSubPackages" value="true" />
              </sqlMapGenerator>
      
              <!-- javaClientGenerator:dao接口生成的地方 -->
              <javaClientGenerator type="XMLMAPPER"
                  targetPackage="com.atguigu.dao"
      
                  targetProject=".\src">
                  <property name="enableSubPackages" value="true" />
              </javaClientGenerator>
      
              <!-- table:指定要逆向生成哪个数据表
              tableName="t_cat":表名
              domainObjectName="":这个表对应的对象名
               -->
              <table tableName="t_cat" domainObjectName="Cat"></table>
              <table tableName="t_employee" domainObjectName="Employee"></table>
              <table tableName="t_teacher" domainObjectName="Teacher"></table>
      
          </context>
      </generatorConfiguration>
      
    • 运行代码生成

      package com.atguigu.test;
      
      import java.io.File;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import org.mybatis.generator.api.MyBatisGenerator;
      import org.mybatis.generator.config.Configuration;
      import org.mybatis.generator.config.xml.ConfigurationParser;
      import org.mybatis.generator.exception.XMLParserException;
      import org.mybatis.generator.internal.DefaultShellCallback;
      
      public class MBGTest {
      
          public static void main(String[] args) throws Exception {
              List<String> warnings = new ArrayList<String>();
              boolean overwrite = true;
              File configFile = new File("mbg.xml");
              ConfigurationParser cp = new ConfigurationParser(warnings);
              Configuration config = cp.parseConfiguration(configFile);
              DefaultShellCallback callback = new DefaultShellCallback(overwrite);
              MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
                      callback, warnings);
              //代码生成
              myBatisGenerator.generate(null);
              System.out.println("生成ok了!");
          }
      
      }
      
    • 测试复杂查询

      package com.atguigu.test;
      
      import static org.junit.Assert.*;
      
      import java.io.IOException;
      import java.io.InputStream;
      import java.util.ArrayList;
      import java.util.Arrays;
      import java.util.Date;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      import java.util.UUID;
      
      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.Before;
      import org.junit.Test;
      
      import com.atguigu.bean.Teacher;
      import com.atguigu.bean.TeacherExample;
      import com.atguigu.bean.TeacherExample.Criteria;
      import com.atguigu.dao.TeacherMapper;
      
      
      
      public class MyBatisTest {
      
          // 工厂一个
          SqlSessionFactory sqlSessionFactory;
      
      
          @Test
          public void test02(){
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //1、测试
              TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
              List<Teacher> teachers = new ArrayList<Teacher>();
              for (int i = 0; i < 1000; i++) {
                  Teacher teacher = new Teacher();
                  teacher.setTeachername(UUID.randomUUID().toString().substring(0, 5));
                  teacher.setClassName(UUID.randomUUID().toString().substring(0, 5));
                  teachers.add(teacher);
              }
              System.out.println("批量保存.....");
              mapper.insertBatch(teachers);
              sqlSession.commit();
              sqlSession.close();
      
      
          }
      
          /**
           * 测试代码生成器
           * @throws IOException
           */
          @Test
          public void test01(){
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //1、测试
              TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
              //2、测试查询所有teacher
              List<Teacher> list = mapper.selectByExample(null);
              for (Teacher teacher : list) {
                  System.out.println(teacher);
              }
      
              //3、带复杂条件的查询
              //select * from t_teacher id=? and teacherName like ?
              //封装查询条件的
              TeacherExample example = new TeacherExample();
              example.setOrderByClause("id DESC");
              //1、使用example创建一个Criteria(查询准则)
              Criteria criteria = example.createCriteria();
              criteria.andIdEqualTo(1);
              criteria.andTeachernameLike("%a%");
      
              System.out.println("======================");
              List<Teacher> list2 = mapper.selectByExample(example);
              for (Teacher teacher : list2) {
                      System.out.println(teacher);
              }
      
              /**
               * 多个复杂条件
               * select * from t_teacher where  (id=? and teacherName like ?) or (address like ? and birth bet)
               */
              TeacherExample example2 = new TeacherExample();
      
      
              //一个Criteria能封装一整个条件
              Criteria criteria2 = example2.createCriteria();
              criteria2.andIdGreaterThan(1);
              criteria2.andTeachernameLike("%a%");
      
              //创建第二个查询条件
              Criteria criteria3 = example2.createCriteria();
              criteria3.andAddressLike("%%");
              criteria3.andBirthDateBetween(new Date(), new Date());
      
              example2.or(criteria3);
              System.out.println("=======-=-=-=-=-=-=-");
              mapper.selectByExample(example2);
      
          }
      
          @Before
          public void initSqlSessionFactory() throws IOException {
              String resource = "mybatis-config.xml";
              InputStream inputStream = Resources.getResourceAsStream(resource);
              sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
          }
      
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值