MyBatis主要组成部分
clipboard.png1. SqlSessionFactoryBuilder(构造器)
根据配置信息或代码生成SqlSessionFactory接口
2. SqlSessionFactory(工厂接口)
依靠工厂来生成SQLSesson(会话)
3. SqlSession(sql处理器)
既可以发送SQL去执行并返回结果,也可以获取Mapper的接口
4. SQL Mqapper(映射规则及SQL定义)
MyBatis的新设计组件,由Java接口和XML文件(或注解)构成,需要给出对应的SQL和映射规则。负责发送SQL去执行。并返回结果。
SqlSessionFactory
MyBatis的应用都是以SqlSessionFactory的实例为中心。SqlSessionFactory的实例是由SqlSessionFactoryBuilder生成的。
注:SqlSessionFactory是一个工厂接口,不是实现类
SqlSessionFactory的任务是创建SQLSession。SQLSession类似于JDBC的Connection对象。
可用XML配置和代码方式创建SQLSessionFactory,推荐使用XML配置方法
SQLSession
SqlSession是一个接口类,相当于前台,主要和程序员交接,调用Executor接口执行相应操作。SqlSession在中间负责接收功能参数,之后返回结果(是一个黑箱操作)
SQLSession类似于JDBC中的Connection对象,需要及时关闭。
SQLSession的执行包括两种方法:1.获取映射器,让映射器通过命名空间和方法名称找到对应的SQL,发送到数据库并执行。2.直接通过命名信息去执行SQL并返回结果。在SQLSession层可以通过update,insert,select,delete等方法,带上SQL的id来操作在XML中配置的SQL,进而完成工作。也支持事物,通过commit和rollback方法提交或者回滚事物。
clipboa1rd.png
映射器 (XML Mapper和Java接口)
映射器是由Java接口和XML文件(或注解)组成,作用是:
- 定义参数类型。
- 描述缓存。
- 描述SQL语句。
- 定义查询结果和POJO的映射关系。
映射器有两种实现方式,1. xml文件描述。2. java代码实现,添加注解方式。
建议使用xml方式
MyBatis生命周期
SQLSessionFactoryBuilder
利用xml配置文件或java编码构建SQLSessionFactory,可构建多个SQLSessionFactory。它是一个构建器,一旦构建出SQLSessionFactory,它的作用就完成了。只存在于方法的局部,作用就是生产SQLSessionFactory。
SQLSessionFactory
SQLSessionFactory的作用是创建SQLSession,每次访问数据库都需要它来创建SQLSession,所以SQLSessionFactory存在于MyBatis的整个生命周期。
通常一个数据库对应一个SQLSessionFactory,避免消耗过多的数据库连接资源。
SQLSession
SQLSession是一个会话,它的生命周期是在请求数据库处理事务的过程当中,相当于JDBC的Connection对象,属于==线程不安全对象==,在涉及多线程时需格外注意,操作数据库需要注意其隔离级别,数据库锁等高级特性。创建并使用完SQLSession后必须及时
关闭,减少资源占用。
Mapper
Mapper是一个接口,没有任何实现类,作用是发送SQL,再返回需要的结果或执行SQL修改数据库的数据。 它是在一个SQLSession事物的方法中使用的,然后废弃。
Mybatis设置
<?xml version = "1.0" encoding = "UTF-8"?>
<configuration><!--配置-->
<properties/><!--属性-->
<settings/><!--设置-->
<typeAliases/><!--类型命名-->
<typeHandlers/><!--类型处理器-->
<objectFactory/><!--对象工厂-->
<plugins/><!--插件-->
<environments><!--配置环境-->
<environment><!--环境变量-->
<transactionManager/><!--事物管理器-->
<dataSource/><!--数据源-->
</environment>
</environments>
<databaseIdProvider/><!--数据库厂商标识-->
<mappers/><!--映射器-->
</configeration>
properties元素
properties是个配置属性的元素,配置文件的上下文中使用。
三种配置方式
- property子元素
- properties配置文件
- 程序参数配置
property子元素
property子元素配置代码如下:
<properties>
<property name = "dirver" value = "com.mysql.jdbc.Dirver"/>
<property name = "url" value = "jdbc:mysql://localhost:3306/mybatis"/>
<property name = "username" value = "root"/>
<property name = "password" value = "123"/>
</properties>
这样我们就可以在上下文中使用配置好的properties属性值。
<dataSourse type = "POOLED">
<property name = "dirver" value = "${dirver}"/>
<property name = "url" value = "${url}"/>
<property name = "username" value = "${username}"/>
<property name = "password" value = "${password}"/>
</dataSourse>
properties配置文件
使用properties配置文件可让多个配置文件重复使用
<!--jdbc.properties-->
dirver = com.mysql.jdbc.Dirver
url = jdbc:mysql://localhost:3306/mybatis
username = root
password = 123
引用变量代码如下:
<properties resource = "jdbc.properties"/>
程序参数传递
在实际对于用户名密码需要进行加密处理,则需要让jdbc.properties中的username和password两个属性使用加密字符串,需要在生产SQLSessionFactory之前转化为明文,使用系统提供的decode(str)方法解密。使用代码方式创建SQLSessionFactory:
InputStream cfgStream = null;
reader cdgReader = null;
InputStream proStream = null;
Reader proReader = null;
Properties properties = null;
try{
//读入配置文件流
cfgStream = Resources.getResourceAsStream("MyBatis-config.xml");
cfgReader = new InputStreamReader(cfgStream);
//读入属性文件
proStream = Resources.getResourceAsStream("jdbc.properties");
proReader = new InputStreamReader(proStream);
properties = new Properties();
properties.load(proReader);
//解密为明文
properties.setProperty("username",decode(properties.getProperty("username")));
properties.setProperty("password",decode(properties.getProperty("password")));
}catch (IOException ex){
Logger.getLogger(SqlSessionFactoryUtil.class.getName()).log(Level.SERVRE,null,ex);
}
sysnchronized(CLASS_LOCK){
if(sqlSessionFactory == null){
//使用属性来创建SQLSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().builder(cfgReader,properties);
}
}
三种配置优先级
通过方法传递 > 读取properties文件 > property直接指定
三种方法不要混合使用,容易造成管理混乱。
优先使用读取properties文件方式。
设置
设置(setting)是MyBatis最复杂的一块配置,也是最重要的配置块之一。
它会改变MyBatis的运行行为,但是即使不配置setting,MyBatis也能正常使用。
完整的setting配置如下:
<settings>
<setting name = "cacheEnabled" value = "true"/>
<setting name = "lazyLoadingEnabled" value = "true"/>
<setting name = "multipleResultSetsEnabled" value = "true"/>
<setting name = "useColumnLabel" value = "true"/>
<setting name = "useGenerateKeys" value = "false"/>
<setting name = "autoMappingBehavior" value = "PARTIAL"/>
<setting name = "defaultExcutorType" value = "SIMPLE"/>
<setting name = "defaultStatementTimeout" value = "25"/>
<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)是一个指代名称,当遇到类全限定名过长时,我们使用typeAliases去代替它。这个名称在MyBatis上下文中使用。别名在MyBatis中分为系统定义别名和自定义别名两类。
别名不区分大小写。
一个typeAliases的实例是在解析配置文件时生成的,然后长期保存在configuration对象中,当我们使用时就不必再次运行生成实例了。
系统自定义别名
MyBatis系统定义了一些经常使用的类型的别名,例如:数值,字符串,日期集合等,可以在MyBatis中直接调用,不要重复定义把他们覆盖。
自定义别名
MyBatis允许自定义别名,代码例如:
<!--自定义别名-->
<typeAliases>
<typeAlias alias = "role" type = "com.learn.chapter2.po.Role"/>
</typeAliases>
当自定义别名过多时,可以定义自动扫描包的范围,并在需要定义的类的上方加注解即可批量定义别名。
<!--扫描包,批量定义别名-->
<typeAliases>
<package name = "com.learn.chapter2.po"/>
<package name = "com.learn.chapter3.po"/>
</typeAliases>
/*
*别名注解
*/
@Alias("role")
public class Role{
//some code
}
不加注解也能加载别名,默认将类名第一个字母变为小写,故一定要避免重名。
typeHandler类型处理器
MyBatis在预处理语句(prepareStatment)中设置一个参数,或从结果集(ResultSet)中取出一个值时,都会用注册了的typeHandler进行处理。
由于数据库的厂商不同,不同的厂商设置的参数可能不同,数据库也可以自定义数据类型,typeHandler允许根据项目的需要自定义设置java传递到数据库的参数中,或者从数据库读出数据,也需要进行特殊处理,这些都是在自定义typeHandler中处理,尤其是枚举类型常常需要使用typeHandler来进行转换。
typeHandler分为系统定义和自定义两种,一般系统定义可满足绝大部分功能。自定义typeHandler务必小心谨慎。
typeHandler常用配置为javaType和jdbcType,作用是将JavaType转化为jdbcType,或者将数据库取出结果从jdbcType转化为JavaType。
.......
ObjectFactory
mybatis在构建一个结果返回的时候,需要用到ObjectFactory(对象工厂)去构建POJO,在MyBatis中也可以定制自己的对象工厂。一般使用默认的ObjectFactory即可。
自定义ObjectFactory需要进行配置
<objectFactory type="com.learn.chapter3.objectFactory.MyObjectFactory">
<property name="name" value="MyObjectFactory" />
</objectFactory>
自定义ObjectFactory需要刷新ObjectFactory接口,而系统自带的DefaultObjectfactory已经实现了ObjectFactory接口,故只需让myObjectFactory基础DefaultObjectFactory即可。实例如下:
//MyObjectFactory
packgae com.learn.chapter3.objectFactory;
improt java util.List;
import java.util.Properties;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.log4j.Logger;
public class MyObjectFactory extends DefaultObjectFactory{
private static final long serialVerSionUID = -381482721604028629L;
Logger log = Logger.getLogger(MyobjectFactory.class);
@Override
public void setProperties(Properties prprty){
log.info("定制属性:"+prprty);
super.setProperties(prprts);
}
@Override
public <T> T create(Class<T> type){
log.info("使用定制对象工厂的create的方法构建单个对象");
return super.create(type);
}
@Override
public <T> T create(Class<T> type, List<Class<?>> list, List<Objetc> list1){
log.info("使用定制对象工厂的create方法构建列表对象");
return super.create(type,list,list1);
}
@Override
public <T> boolean isCollection(Class<T> type){
return super.isCollection(type);
}
}
插件
比较复杂,会出现一些覆盖MyBatis内部核心的行为。
environment配置环境
注册数据源
配置环境可以注册多个数据源(dataSource),每个数据源需要进行数据库源配置及数据库事物(transactionManager)配置。
连接池数据配置示例:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="autoCommit" value="false"/>
</transactionManager>
<dataSource type="POOLED">
<property name="dirver" value="com.mysql.jdbc.Dirver"/>
<property name="url" value="jdbc:mysql://localhost:3306/oa"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</dataSource>
</environment>
</environments>
上述代码中environments中default属性,标明在缺省情况下启用哪个数据源。
- environment元素是配置一个数据源的,属性id是设置这个数据源的标识,以方便mybatis在上下文中使用它。
- transactionManager配置数据源的数据库事物,其中type属性有三种配置方式。
- JDBC,采用JDBC方式管理事物,在独立编码中常常使用。
- MANAGED,采用容器的方式管理事物,在JNDI数据源中使用。
- 自定义,由使用者自定义数据库事物管理办法,适用于特殊应用。
- property元素可以配置数据源各类属性,这里的autoCommit=false,则是要求数据源不自动提交。
- dataSource标签配置的是数据源的连接信息,type属性提供数据库的连接方式的配置,在mybatis中有几种连接方式:
- UNPOOLED,非连接池数据库。
- POOLED,连接池数据库
- JNDI,JNDI数据源。
- 自定义数据源。
其中property元素是定义数据库连接的各类参数。
数据库事物
数据库事务Mybatis交由SqlSession控制,可以通过SqlSession提交(commit)或者回滚(rollback)。插入一个角色对象,如果成功就提交,否则就回滚。
try{
sqlSession = SqlSessionFactoryUtil.openSqlSession();
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
int count = roleMapper.insertRole(role);
sqlSession.commit();
return count;
}catch(Exception ex){
sqlSession.rollback();
}finally{
sqlSession.close();
}
大部分时候都是用Spring框架控制数据库事物
dataSourceIdProvider数据库厂商标识
可选择使用系统默认规则和不使用系统默认规则。
引入映射器的方法
映射器是mybatis最复杂,最核心的组件。
- 首先定义映射器接口
package com.learn.chapter3.mapper;
import java.util.List;
import com.learn.chapter3.po.Role;
public interface RoleMapper {
public Role getRole(Long id);
}
- 其次给出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.learn.chapter3.mapper.RoleMapper">
<select id="getRole" paramenterType="long" resultType="com.learn.chapter3.po.Role">
select id,role_name as roleName, note from t_role where id=#{id}
</select>
</mapper>
引入映射器的常用方法:
- 用文件路径引入映射器
<mappers>
<mapper resource="com/learn/chapter3/mapper/roleMapper.xml"/>
</mappers>
- 用包名映入映射器
<mappers>
<package name="com.learn.chapter3.mapper"/>
</mappers>
- 用类注册引入映射器
<mappers>
<mapper class="com.learn.chapter3.mapper.UserMapper"/>
<mapper class="com.learn.chapter3.mapper.RoleMapper"/>
</mappers>
- 用userMapper.xml引入映射器
<mappers>
<mapper url="file:///var/mappers/com/learn/chapter3/mapper/roleMapper/xml"/>
<mapper url="file:///var/mappers/com/learn/chapter3/mapper/RoleMapper.xml"/>
</mappers>
映射器
MyBatis是针对映射器构造的SQL构建的轻量级框架,并且通过配置生成对应的JavaBean返回给调用者,这些配置主要便是映射器。
映射器的主要元素
- select ,查询语句,最常用最复杂的元素。可以自定义参数,返回结果集等
- insert, 插入语句。执行后返回一个整数,代表插入的条数。
- update,更新语句。执行后返回一个整数,代表更新的条数。
- delete,删除语句。执行后返回一个整数,代表删除的条数。
- parameterMap,定义参数映射关系。即将被删除的元素,不建议使用。
- sql, 允许定义一部分的SQL,然后可在各个地方引用它。
- resultMap, 用来描述从数据库中结果集中来加载对象,最复杂,最强大的元素。
- cache,给命名空间缓存配置。
- cache-ref,其他命名空间缓存配置引用。
select
简单select数据类型的例子
<select id="countFirstName" parameterType="String" resultType="int">
select count(*) as total from t_user where name like concat(#{firstName},'%')
</select>
在Dao接口中定义方法
public int countFirstName(String firstName);
- id 标出了这条sql
- paramenterType 定义参数类型
- resultType定义了返回值类型
自动映射
setting元素中有autoMappingBehavior参数,当它不设置为NONE时,MyBatis会设置自动映射功能。只要返回的Sql的列名和javaBean的属性一致,mybatis会帮我们回填这些字段,无需任何配置。
注:数据库规范单词间用下划线分隔,java中使用驼峰式命名,可以使用列的别名使mybatis自动映射,也可以直接配置文件中开启驼峰式命名方式。
传递多个参数
使用map传递多个参数
使用Map接口作为参数实现多参数传递
<select id="findRoleByMap" parameterType="map" resultMap="roleMap">
select id, role_name, note
from t_role
where role_name like concat('%',#{roleName},'%')
and note like concat('%',#{note},'%')
</select>
RoleDao接口:
public List<Role> findRoleByMap(Map<String,String> params);
参数传递代码如下:
Map<String,String> paramsMap = new HashMap<String,String>();
paramsMap.put("roleName", "me");
paramsMap.Put("note","te");
role
clipbo32ard.png
网友评论