1.两个核心对象
①SqlSessionFactory
SqlSessionFactory是单个数据库映射关系经过编译后的内存镜像,其主要作用是创建SqlSession。SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象来构建,而SqlSessionFactoryBuilder则可以通过XML配置文件或一个预先定义好的Configuration实例构建出SqlSessionFactory的实例。
通过XML配置文件构建出的SqlSessionFactory实例:
// 1.读取配置文件
InputStream is = Resources.getResourceAsStream("配置文件位置");
// 2.构建工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSessionFactory对象是线程安全的,它一旦被创建,在整个应用执行期间都会存在。通常每一个数据库都会只对应一个SqlSessionFactory,所以在构建SqlSessionFactory实例时,建议使用单例模式。
在创建SqlSessionFactory 对象的过程中, 首先解析mybatis-config.xml 配置文件,读取配置文件中的mappers 配置后会读取全部的Mapper. xml 进行具体方法的解析,在这些解析完成后, SqlSessionFactory 就包含了所有的属性配置和执行SQL 的信息。
②SqlSession
SqlSession是应用程序与持久层之间执行交互操作的一个单线程对象,其主要作用是执行持久化操作,它是MyBatis中最重要的内容。SqlSession对象包含了数据库中所有执行SQL操作的方法,由于其底层封装了JDBC连接,所以可以直接使用其实例来执行已映射的SQL语句。
SqlSession实例是线程不安全的,因此其使用范围最好在一次请求或一个方法中,绝不能将其放在一个类的静态字段、实例字段或任何类型的管理范围(如Servlet的HttpSession)中使用。使用完SqlSession对象之后,要及时地关闭它。
一定不要忘记关闭SqlSession ,否则会因为连接没有关闭导致数据库连接数过多,造成系统崩溃。
MyBatis有内建的SqlSession级别的缓存机制,用于缓存Select语句查询出来的结果,但此时必须是同一个SqlSession对象。
获取SqlSession实例的代码:SqlSession sqlSession = SqlSessionFactory.openSession();
注:为了简化开发,通常将创建SqlSessionFactory实例对象和创建SqlSession实例对象封装到一个工具类中,然后通过工具类来创建SqlSession。 例,
package com.money.util;
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;
public class MyBatisSqlSessionFactory {
private static SqlSessionFactory factory;
public static SqlSessionFactory getSqlSessionFactory() {
try {
// 1.读取配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 2.构建工厂对象
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
return factory;
}
/**
* 获取SQLSession对象,手动提交事务
*
* @return
*/
public static SqlSession openSession() {
return openSession(false);
}
/**
* 获取SQLSession对象,自动提交事务
*
* @param flag
* @return
*/
public static SqlSession openSession(boolean flag) {
return getSqlSessionFactory().openSession(flag);
}
}
2.配置文件主要元素
注:这里的配置文件指的是mybatis-config.xml文件。
①< configuration>元素
在MyBatis框架的核心配置文件中,< configuration>元素是配置文件的根元素,其他元素都要在< configuration>元素内配置。MyBatis配置文件中的主要元素:
注:< configuration>的子元素必须按照上图中由上到下的顺序进行配置,否则MyBatis在解析XML配置文件的时候会报错。
②< properties>元素
< properties>是一个配置属性的元素,该元素通常用于将内部的配置外在化,即通过引用外部的配置文件来动态地替换内部定义的属性。例如,数据库的连接等属性,这样就更方便程序的运行和部署。
~~创建db.properties的配置文件,文件内容如下:
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:XE
username=money
jdbc.password=money
~~在MyBatis配置文件mybatis-config.xml中配置
<properties resource="db.properties">
~~修改配置文件中数据库连接的信息:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
dataSource>
environment>
environments>
完成上述配置后,dataSource中连接数据库的4个属性(driver、url、username和password)值将会由db.properties文件中对应的值来动态替换。
注:当使用外部引用时继续配置property数据库的用户名和密码,此时db.properties文件中的值优先级高,即外部配置文件优先级更高。 例,
<properties resource="db.properties">
<property name="username" value="123" />
<property name="password" value="123" />
properties>
此时,使用的是db.properties文件中配置的信息。
在< properties>元素定义的子元素在整个XML文件中都可以通过${name值}来获取其值。例,
<properties>
<property name="uesrname" value="123" />
properties>
此时在文件中就可以通过${username}来获取值。
③< settings>元素
< settings>元素主要用于改变MyBatis运行时的行为,例如开启二级缓存、开启延迟加载等。虽然不配置< settings>元素,也可以正常运行MyBatis。
< settings>元素中的常见配置及其描述:
使用方式:
<settings>
<setting name="cacheEnabled" value="true" />
settings>
④< typeAliases>元素
< typeAliases>元素用于为配置文件中的Java类型设置一个别名。别名的设置与XML配置相关,其使用的意义在于减少全限定类名的冗余。别名的使用忽略大小写。
使用< typeAliases>元素配置别名:
<typeAliases>
<typeAlias type="com.money.bean.Book" alias="Book" />
typeAliases>
< typeAliases>元素的子元素< typeAlias>中的type属性用于指定需要被定义别名的类的全限定名;alias属性的属性值Book就是自定义的别名,它可以代替com.money.bean.Book在MyBatis文件的任何位置的使用。如果省略alias属性,MyBatis会默认将类名首字母小写后的名称作为别名。
当POJO类过多时,还可以通过自动扫描包的形式自定义别名:
<typeAliases>
<package name="com.money.bean"/>
typeAliases>
< typeAliases>元素的子元素< package>中的name属性用于指定要被定义别名的包,MyBatis会将所有com.money.bean包中的POJO类以首字母小写的非限定类名来作为它的别名。例,com.money.bean.Book的的别名是book。
还可以在程序中使用注解,则别名为其注解的值:
@Alias(value = "book")
public class Book {
}
注:@Alias("book")
也可以,@Alias注解将会覆盖配置文件中的< typeAliases>定义
注:@Alias 要和< package name=""/>标签配合使用,Mybatis会自动查看指定包内的类别名注解,如果没有这个注解,那么默认的别名就是类的名字,不区分大小写。
除了可以使用< typeAliases>元素自定义别名外,MyBatis框架还默认为许多常见的Java类型(如数值、字符串、日期和集合等)提供了相应的类型别名:
注:上表所列举的别名可以在MyBatis中直接使用,别名不区分大小写。
⑤< typeHandler>元素(类型处理器)
当MyBatis将一个Java对象作为输入参数执行INSERT语句操作时,它会创建一个PreparedStatement对象,并且使用setXXX()方法对?号占位符 设置相应的参数值 。这里,XXX可以是int,String,Date 等 Java对象属性类型的任意一个。例,
<insert id="insertStudent" parameterType="Student">
INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL)
VALUES(#{studId},#{name},#{email})
insert>
当执行上面的语句时,MyBatis将采取以下操作:
创建一个有占位符的PreparedStatement接口,例:PreparedStatement ps = connection.prepareStatement ("INSERT INTO STUDENTS(STU_ID,NAME,EMAIL) VALUES(?,?,?)");
接下来就像JDBC的操作一样,针对不同的?采用合适setXXX方法去设置参数值。例,stuId是Integer类型,所以会使用setInt()方法:ps.setInt(1,student.getStuId());
但MyBatis是怎么知道对于Integer类型属性使用setInt()和String类型属性使用setString()方法呢?其实MyBatis是通过使用类型处理器typeHandlers来决定这样做的。typeHandler的作用就是将预处理语句中传入的参数从javaType(Java类型)转换为jdbcType(JDBC类型),或者从数据库取出结果时将jdbcType转换为javaType。
MyBatis对于以下的类型使用内置的类型处理器:所有的基本数据类型、基本类型的包装类型、 byte[]、java.util.Date、java.sql.Date、java,sql.Time、java.sql.Timestamp、java枚举类型等:
当MyBatis框架所提供的这些类型处理器不能够满足需求时,还可以通过自定义的方式对类型处理器进行扩展(自定义类型处理器可以通过实现TypeHandler接口或者继承BaseTypeHandler类来定义)。< typeHandler>元素就是用于在配置文件中注册自定义的类型处理器的。使用方式:
~~注册一个类的类型处理器:
<typeHandlers>
<typeHandler handler="com.money.bean.Book" />
typeHandlers>
子元素< typeHandler>的handler属性用于指定在程序中自定义的类型处理器类。
~~注册一个包中所有的类型处理器:
<typeHandlers>
<package name="com.money.bean"/>
typeHandlers>
子元素< package>的name属性用于指定类型处理器所在的包名,使用此种方式后,系统会在启动时自动地扫描com.money.bean包下所有的文件,并把它们作为类型处理器。
继承BaseTypeHandler类需要实现它的方法:
package com.money.bean;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
public class BookTypeHandler extends BaseTypeHandler<Book> {
// 查询中遇到Book类型的应该如何封装(使用列名封装)
@Override
public Book getNullableResult(ResultSet rs, String columnName) throws SQLException {
// TODO Auto-generated method stub
return null; //此处通过结果集rs的getString方法获取对应的数据库列中的值,将它如何转换为需要的类型对象需要自己设置
}
// 查询中遇到Book类型的应该如何封装(使用列的下标)
@Override
public Book getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
return null; 此处通过结果集rs的getString方法获取对应的数据库列中的值,将它如何转换为需要的类型对象需要自己设置
}
// CallableStatement使用中遇到了Book类型的应该如何封装
@Override
public Book getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
return null; //此处的cs和rs类似
}
// 遇到参数类型为Book的值的时候应该如何在ps中设置值
@Override
public void setNonNullParameter(PreparedStatement ps, int arg1, Book book, JdbcType arg3) throws SQLException {
// TODO Auto-generated method stub
ps.setString(arg1, book.toString()); //在数据库中需要什么类型就用什么set方法,arg1是PreparedStatement的语句中需要设置该特殊类型的位置
}
}
MyBatis框架每次创建结果对象的新实例时,都会使用一个对象工厂(ObjectFactory)的实例来完成。MyBatis中默认的ObjectFactory的作用就是实例化目标类,它既可以通过默认构造方法实例化,也可以在参数映射存在的时候通过参数构造方法来实例化。
MyBatis中默认的ObjectFactory是由org.apache.ibatis.reflection.factory.DefaultObjectFactory来提供服务,如果想覆盖ObjectFactory的默认行为,则可以通过自定义ObjectFactory来实现:
~~自定义一个对象工厂。自定义的对象工厂需要实现ObjectFactory接口,或者继承DefaultObjectFactory类:
public class MyObjectFactory extends DefaultObjectFactory {
}
~~在配置文件中使用< objectFactory>元素配置自定义的ObjectFactory:
<objectFactory type="com.money.bean.MyObjectFactory">
<property name="" value="MyObjectFactory" />
objectFactory>
⑦< plugins>元素
< plugins>元素的作用就是配置用户所开发的插件。
⑧< environments>元素
在配置文件中,< environments>元素用于对环境进行配置。MyBatis的环境配置实际上就是数据源的配置,我们可以通过< environments>元素配置多种数据源,即配置多种数据库:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver"
value="oracle.jdbc.driver.OracleDriver" />
<property name="url"
value="jdbc:oracle:thin:@127.0.0.1:1521:XE" />
<property name="username" value="123" />
<property name="password" value="123" />
dataSource>
environment>
environments>
< environments>元素是环境配置的根元素,它包含一个default属性,该属性用于指定默认的环境ID。< environment>是< environments>元素的子元素,它可以定义多个,其id属性用于表示所定义环境的ID值,当有多个environment数据库环境时,可以根据environments的default属性值为environment的id属性来指定哪个数据库环境起作用,也可以根据下面的代码改变数据库环境。 在< environment>元素内,包含事务管理和数据源的配置信息,其中< transactionManager>元素用于配置事务管理,它的type属性用于指定事务管理的方式,即使用哪种事务管理器;< dataSource>元素用于配置数据源,它的type属性用于指定使用哪种数据源,该元素至少要配置4要素:driver、url、username、password。
在获取SqlSessionFactory对象时,如果没有指定用哪个数据库环境,则build方法的参数默认是environments的default属性值,如果想要更换数据库环境,可以将build方法的第二个参数改为要更换的数据库环境的environment的id值。例,
// 1.读取配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 2.构建工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); //默认是environments的default属性值
// 1.读取配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 2.构建工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is,"development"); //指定environment的id值
在MyBatis中,可以配置两种类型的事务管理器,分别是JDBC和MANAGED:
注:如果项目中使用的是Spring+ MyBatis,则没有必要在MyBatis中配置事务管理器,因为实际开发中,会使用Spring自带的管理器来实现事务管理。
⑨ < mappers>元素
< mappers>元素用于指定MyBatis映射文件的位置,引入映射文件方法有4种:
使用xml文件来配置sql语句:
~~使用类路径引入:
<mappers>
<mapper resource="com/money/mappers/BookMapper.xml" />
mappers>
~~使用本地文件路径引入:
<mappers>
<mapper url="" />
mappers>
使用注解来配置sql语句:
~~使用接口类引入:
<mappers>
<mapper class="com.money.mappers.BookMapper" />
mappers>
~~使用包名引入:
<mappers>
<package name="com.money.mappers"/>
mappers>