MyBatis核心知识

14 篇文章 0 订阅
13 篇文章 0 订阅

1.MyBatis核心对象

1.1SqlSessionFactory

SqlSessionFactory是单个数据库映射关系经过编译的内存镜像,主要用来创建SqlSession。
通过xml配置创建SqlSessionFactory实例

String resource = "resource/mybatis.xml";
		// 1.读取配置文件
		InputStream inputStream = Resources.getResourceAsStream(resource);
		// 2.根据配置文件构建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
				.build(inputStream);

SqlSessionFactory对象是线程安全的,一旦被创建,在整个应用程序期间都会存在,所以如果大量的创建SqlSessionFactory对象,很可能会耗完数据库的连接资源,所以SqlSessionFactory尽可能使用单例模式。
SqlSessionFactory有哪些方法:

public interface SqlSessionFactory {

  SqlSession openSession();

  SqlSession openSession(boolean autoCommit);
  SqlSession openSession(Connection connection);
  SqlSession openSession(TransactionIsolationLevel level);

  SqlSession openSession(ExecutorType execType);
  SqlSession openSession(ExecutorType execType, boolean autoCommit);
  SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
  SqlSession openSession(ExecutorType execType, Connection connection);

  Configuration getConfiguration();

}

1.2SqlSession

SqlSession是应用程序与持久层之执行交互操作的一个单线程对象,主要执行持久化操作;SqlSession底层封装了JDBC连接,所以可以直接用SqlSession实例执行已映射的SQL语句。
SqlSession线程不安全,所以SqlSession的使用范围应当在局部使用,使用完毕后及时的关闭SqlSession,其他需要使用的地方需要重新获取。
SqlSession的方法非常的多:
查询:

/**
   * Retrieve a single row mapped from the statement key
   * @param <T> the returned object type
   * @param statement
   * @return Mapped object
   */
  <T> T selectOne(String statement);

  /**
   * Retrieve a single row mapped from the statement key and parameter.
   * @param <T> the returned object type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @return Mapped object
   */
  <T> T selectOne(String statement, Object parameter);

  /**
   * Retrieve a list of mapped objects from the statement key and parameter.
   * @param <E> the returned list element type
   * @param statement Unique identifier matching the statement to use.
   * @return List of mapped object
   */
  <E> List<E> selectList(String statement);

  /**
   * Retrieve a list of mapped objects from the statement key and parameter.
   * @param <E> the returned list element type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @return List of mapped object
   */
  <E> List<E> selectList(String statement, Object parameter);

  /**
   * Retrieve a list of mapped objects from the statement key and parameter,
   * within the specified row bounds.
   * @param <E> the returned list element type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @param rowBounds  Bounds to limit object retrieval
   * @return List of mapped object
   */
  <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);

  /**
   * The selectMap is a special case in that it is designed to convert a list
   * of results into a Map based on one of the properties in the resulting
   * objects.
   * Eg. Return a of Map[Integer,Author] for selectMap("selectAuthors","id")
   * @param <K> the returned Map keys type
   * @param <V> the returned Map values type
   * @param statement Unique identifier matching the statement to use.
   * @param mapKey The property to use as key for each value in the list.
   * @return Map containing key pair data.
   */
  <K, V> Map<K, V> selectMap(String statement, String mapKey);

  /**
   * The selectMap is a special case in that it is designed to convert a list
   * of results into a Map based on one of the properties in the resulting
   * objects.
   * @param <K> the returned Map keys type
   * @param <V> the returned Map values type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @param mapKey The property to use as key for each value in the list.
   * @return Map containing key pair data.
   */
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);

  /**
   * The selectMap is a special case in that it is designed to convert a list
   * of results into a Map based on one of the properties in the resulting
   * objects.
   * @param <K> the returned Map keys type
   * @param <V> the returned Map values type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @param mapKey The property to use as key for each value in the list.
   * @param rowBounds  Bounds to limit object retrieval
   * @return Map containing key pair data.
   */
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);

  /**
   * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
   * @param <T> the returned cursor element type.
   * @param statement Unique identifier matching the statement to use.
   * @return Cursor of mapped objects
   */
  <T> Cursor<T> selectCursor(String statement);

  /**
   * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
   * @param <T> the returned cursor element type.
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @return Cursor of mapped objects
   */
  <T> Cursor<T> selectCursor(String statement, Object parameter);

  /**
   * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
   * @param <T> the returned cursor element type.
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @param rowBounds  Bounds to limit object retrieval
   * @return Cursor of mapped objects
   */
  <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);

  /**
   * Retrieve a single row mapped from the statement key and parameter
   * using a {@code ResultHandler}.
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @param handler ResultHandler that will handle each retrieved row
   */
  void select(String statement, Object parameter, ResultHandler handler);

  /**
   * Retrieve a single row mapped from the statement
   * using a {@code ResultHandler}.
   * @param statement Unique identifier matching the statement to use.
   * @param handler ResultHandler that will handle each retrieved row
   */
  void select(String statement, ResultHandler handler);

  /**
   * Retrieve a single row mapped from the statement key and parameter
   * using a {@code ResultHandler} and {@code RowBounds}
   * @param statement Unique identifier matching the statement to use.
   * @param rowBounds RowBound instance to limit the query results
   * @param handler ResultHandler that will handle each retrieved row
   */
  void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);

增加

/**
   * Execute an insert statement.
   * @param statement Unique identifier matching the statement to execute.
   * @return int The number of rows affected by the insert.
   */
  int insert(String statement);

  /**
   * Execute an insert statement with the given parameter object. Any generated
   * autoincrement values or selectKey entries will modify the given parameter
   * object properties. Only the number of rows affected will be returned.
   * @param statement Unique identifier matching the statement to execute.
   * @param parameter A parameter object to pass to the statement.
   * @return int The number of rows affected by the insert.
   */
  int insert(String statement, Object parameter);

更新

/**
   * Execute an update statement. The number of rows affected will be returned.
   * @param statement Unique identifier matching the statement to execute.
   * @return int The number of rows affected by the update.
   */
  int update(String statement);

  /**
   * Execute an update statement. The number of rows affected will be returned.
   * @param statement Unique identifier matching the statement to execute.
   * @param parameter A parameter object to pass to the statement.
   * @return int The number of rows affected by the update.
   */
  int update(String statement, Object parameter);

删除

/**
   * Execute a delete statement. The number of rows affected will be returned.
   * @param statement Unique identifier matching the statement to execute.
   * @return int The number of rows affected by the delete.
   */
  int delete(String statement);

  /**
   * Execute a delete statement. The number of rows affected will be returned.
   * @param statement Unique identifier matching the statement to execute.
   * @param parameter A parameter object to pass to the statement.
   * @return int The number of rows affected by the delete.
   */
  int delete(String statement, Object parameter);

事务提交

/**
   * Flushes batch statements and commits database connection.
   * Note that database connection will not be committed if no updates/deletes/inserts were called.
   * To force the commit call {@link SqlSession#commit(boolean)}
   */
  void commit();

  /**
   * Flushes batch statements and commits database connection.
   * @param force forces connection commit
   */
  void commit(boolean force);

事务回滚

 /**
   * Discards pending batch statements and rolls database connection back.
   * Note that database connection will not be rolled back if no updates/deletes/inserts were called.
   * To force the rollback call {@link SqlSession#rollback(boolean)}
   */
  void rollback();

  /**
   * Discards pending batch statements and rolls database connection back.
   * Note that database connection will not be rolled back if no updates/deletes/inserts were called.
   * @param force forces connection rollback
   */
  void rollback(boolean force);

其他

/**
   * Flushes batch statements.
   * @return BatchResult list of updated records
   * @since 3.0.6
   */
  List<BatchResult> flushStatements();

  /**
   * Closes the session
   */
  @Override
  void close();

  /**
   * Clears local session cache
   */
  void clearCache();

  /**
   * Retrieves current configuration
   * @return Configuration
   */
  Configuration getConfiguration();

  /**
   * Retrieves a mapper.
   * @param <T> the mapper type
   * @param type Mapper interface class
   * @return a mapper bound to this SqlSession
   */
  <T> T getMapper(Class<T> type);

  /**
   * Retrieves inner database connection
   * @return Connection
   */
  Connection getConnection();

1.3总结

通过上述2点,可以知道SqlSessionFactory是线程安全的,应用程序整个期间都会存在,但是不能拥有多个实例,否则会耗尽数据库资源。
SQLSession是线程不安全的,每次使用都需要从SqlSessionFactory获取 ,而且只能在局部使用,无法共享,每次使用完必须关闭。

所以综上所述,使用SqlSessionFactory获取SqlSession时,最好使用工具类处理:

package util;

import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisSessionUtils {

	private static SqlSessionFactory sessionFactory = null;
	
	private static final String PATH="resource/mybatis.xml";
	
	static{
		try{
			Reader reader = Resources.getResourceAsReader(PATH);
			sessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (Exception e){
			e.printStackTrace();
		}
	}
	
	public static SqlSession getSession(){
		return sessionFactory.openSession();
	}
}

2.配置文件

2.1主要元素

在这里插入图片描述
configuration的子元素必须按照上述顺序进行配置。

2.2properties元素

properties元素是一个配置属性的元素,用于将内部的配置外在化,通过外部的配置动态的替换内部的属性。
ojdbc.properties

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:oracle
username=study
password=study

mybatis.xml

<?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>
  <properties resource="property/ojdbc.properties"></properties>
  <environments default="oracle">
    <environment id="oracle">
      <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>
  <mappers>
    <mapper resource="mapper/PeopleMapper.xml"/>
  </mappers>
</configuration>

2.3setting元素

setting元素用于改变MyBatis运行时的行为,例如开启二级缓存、开启延时加载等等。

<!-- 改变运行时行为 -->
  <settings>
  	<!-- value是默认值 -->
  	<!-- 全局缓存全局 -->
  	<setting name="cacheEnabled" value="false"/>
  	<!-- 延迟加载全局 -->
  	<setting name="lazyLoadingEnabled" value="false"/>
  	<!-- 关联对象属性的延迟加载 -->
  	<setting name="aggressiveLazyLoading" value="true"/>
  	<!-- 单一语句返回多结果集 -->
  	<setting name="multipleResultSetsEnabled" value="true"/>
  	<!-- 列标签代替列名 -->
  	<setting name="useColumnLabel" value="true"/>
  	<!-- JDBC支持自动生成主键 -->
  	<setting name="useGeneratedKeys" value="false"/>
  	<!-- 如何自动映射列到字段或者属性 -->
  	<!-- NONE|FULL -->
  	<setting name="autoMappingBehavior" value="PARTIAL"/>
  	<!-- 默认的执行器 -->
  	<!-- REUSE|BATCH -->
  	<setting name="defaultExecutorType" value="SIMPLE"/>
  	<!-- 设置超时时间 -->
  	<!-- 正整数 -->
  	<setting name="defaultStatementTimeout" value=""/>
  	<!-- 自动驼峰命名规则 -->
  	<setting name="mapUnderscoreToCamelCase" value="false"/>
  	<!-- 为空值指定JDBC类型 -->
  	<!-- NULL|VARCHAR -->
  	<setting name="jdbcTypeForNull" value="OTHER"/>
  </settings>

2.4typeAliases

<typeAliases>
	  <!-- 配置别名 -->
  	<typeAlias type="domain.People" alias="people"/>
  	<!-- 自动扫描 (类首字母小写)-->
  	<package name="domain"/>
  </typeAliases>

注解

@Alias(value = "people")
public class People implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -3270893239281340723L;
}

2.5typeHandler

类型处理器

<typeHandlers>
  	<!-- 单个类的类型处理器 -->
  	<typeHandler handler="domain.People"/>
  	<!-- 注册一个包中所有类的类型处理器 -->
  	<package name="domain"/>
  </typeHandlers>

2.6objectFactory

实例化工厂
默认:

/**
 *    Copyright 2009-2018 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.reflection.factory;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.ibatis.reflection.ReflectionException;
import org.apache.ibatis.reflection.Reflector;

/**
 * @author Clinton Begin
 */
public class DefaultObjectFactory implements ObjectFactory, Serializable {

  private static final long serialVersionUID = -8855120656740914948L;

  @Override
  public <T> T create(Class<T> type) {
    return create(type, null, null);
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
    Class<?> classToCreate = resolveInterface(type);
    // we know types are assignable
    return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
  }

  @Override
  public void setProperties(Properties properties) {
    // no props for default
  }

  private  <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
    try {
      Constructor<T> constructor;
      if (constructorArgTypes == null || constructorArgs == null) {
        constructor = type.getDeclaredConstructor();
        try {
          return constructor.newInstance();
        } catch (IllegalAccessException e) {
          if (Reflector.canControlMemberAccessible()) {
            constructor.setAccessible(true);
            return constructor.newInstance();
          } else {
            throw e;
          }
        }
      }
      constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
      try {
        return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
      } catch (IllegalAccessException e) {
        if (Reflector.canControlMemberAccessible()) {
          constructor.setAccessible(true);
          return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
        } else {
          throw e;
        }
      }
    } catch (Exception e) {
      StringBuilder argTypes = new StringBuilder();
      if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) {
        for (Class<?> argType : constructorArgTypes) {
          argTypes.append(argType.getSimpleName());
          argTypes.append(",");
        }
        argTypes.deleteCharAt(argTypes.length() - 1); // remove trailing ,
      }
      StringBuilder argValues = new StringBuilder();
      if (constructorArgs != null && !constructorArgs.isEmpty()) {
        for (Object argValue : constructorArgs) {
          argValues.append(String.valueOf(argValue));
          argValues.append(",");
        }
        argValues.deleteCharAt(argValues.length() - 1); // remove trailing ,
      }
      throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
    }
  }

  protected Class<?> resolveInterface(Class<?> type) {
    Class<?> classToCreate;
    if (type == List.class || type == Collection.class || type == Iterable.class) {
      classToCreate = ArrayList.class;
    } else if (type == Map.class) {
      classToCreate = HashMap.class;
    } else if (type == SortedSet.class) { // issue #510 Collections Support
      classToCreate = TreeSet.class;
    } else if (type == Set.class) {
      classToCreate = HashSet.class;
    } else {
      classToCreate = type;
    }
    return classToCreate;
  }

  @Override
  public <T> boolean isCollection(Class<T> type) {
    return Collection.class.isAssignableFrom(type);
  }

}

自定义

package factory;

import java.util.List;
import java.util.Properties;

import org.apache.ibatis.reflection.factory.DefaultObjectFactory;

public class ClassFactory extends DefaultObjectFactory{

	/**
	 * 
	 */
	private static final long serialVersionUID = -9058254644564555623L;

	@Override
	public <T> T create(Class<T> type) {
		return super.create(type);
	}

	@Override
	public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes,
			List<Object> constructorArgs) {
		return super.create(type, constructorArgTypes, constructorArgs);
	}

	@Override
	public void setProperties(Properties properties) {
		super.setProperties(properties);
	}

	@Override
	protected Class<?> resolveInterface(Class<?> type) {
		return super.resolveInterface(type);
	}

	@Override
	public <T> boolean isCollection(Class<T> type) {
		return super.isCollection(type);
	}

	
}

配置使用

  <!-- 配置类处理器  -->
  <objectFactory type="factory.ClassFactory">
  	<property name="name" value="ClassFactory"/>
  </objectFactory>

2.7plugins

拦截插件的调用配置

2.8environments

环境配置

<!-- 环境配置 -->
  <environments default="oracle">
    <environment id="oracle">
      <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>

2.9.数据源类型

2.9.1UNPOOLED

每次请求时都会打开和关闭连接

2.9.2POOLED

“池”的概念处理JDBC连接对象

2.9.3JNDI

在EJB或者应用服务器中使用,可以集中或在外部配置数据源,通过JNDI上下文引用。

2.10mappers

用于指定mapper.xml的位置

<mappers>
  	<!-- 类路径引入 -->
    <mapper resource="mapper/PeopleMapper.xml"/>
    <!-- 本地文件路径引入 -->
    <mapper url="file:///D:/PeopleMapper.xml"/>
    <!-- 使用接口类引入 -->
    <!-- 配置的是接口的类路径 -->
    <mapper class="intf.PeopleDao"/>
    <!-- 使用包名引入 -->
    <package name="intf"/>
  </mappers>

3.映射文件

mapper->:

select
insert
update
delete
sql
cache
cache-ref
resultMap

3.1select

<select id="selectPeopleById" resultType="domain.People"
  	parameterType="Long">
    	select * from people where id = #{id}
  </select>

id与命名空间联合使用定位,唯一
parameterType参数的全类名或者别名
resultType返回的全类名或者别名
resultMap外部resultMap的引用
flushCache清空本地缓存和二级缓存
useCache控制二级缓存的开关
timeout设置超时,秒
fetchSize获取总数
statementType设置使用JDBC的工作的Statement
resultSetType表示结果集的类型

3.2insert

<insert id="addPeople" parameterType="domain.People">
  		insert into people(id,name,age,sex) 
  		values(SEQ_PEOPLE.NEXTVAL,#{name},#{age},#{sex})
  </insert>

keyProperty插入或者更新操作返回值赋给属性
keyColumn设置第几列是主键(主键不是表中第一列时需要设置,主键联合用逗号分隔)
useGeneratedKeys获取数据库内部生产的主键(自增主键。。)

3.3update

<update id="updatePeople" parameterType="domain.People">
  		update people set name=#{name},age=#{age},sex=#{sex} where id=#{id}
  </update>

3.4delete

<delete id="deletePeopleById" parameterType="Long">
  		delete people p where p.id=#{id}
  </delete>

3.5sql

重复的sql片段

<sql id="str_select">
  	p.id,p.name,p.age,p.sex
  </sql>
  <select id="selectWithSql">
  	select <include refid="str_select"></include> from people p
  </select>

3.6resultMap

结果集映射

<!-- resultMap结构 -->
  <resultMap type="domain.People" id="resultMapPeople">
  	<!-- 构造注入 -->
  	<constructor>
  		<!-- id注入 -->
  		<idArg/>
  		<!-- 普通结果 -->
  		<arg/>
  	</constructor>
  	<!-- 主键 -->
  	<id property="id" column="id"/>
  	<!-- 普通结果 -->
  	<result property="name" column="name"/>
  	<result property="age" column="age"/>
  	<result property="sex" column="sesx"/>
  	<!-- 一对一关联 -->
  	<association property=""></association>
  	<!-- 一对多关联 -->
  	<collection property=""></collection>
  	<!-- 使用结果来决定使用哪个结果映射 -->
  	<discriminator javaType="">
  		<!-- 基于某些值的结果映射 -->
  		<case value=""></case>
  	</discriminator>
  </resultMap>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值