Mybatis-3
一.MyBatis的工作原理
(1)读取MyBatis配置文件mybatis-config.xml。mybatis-config.xml作为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接。
(2)加载映射文件Mapper.xml。Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载才能执行。mybatis-config.xml可以加载多个配置文件,每个配置文件对应数据库中的一张表。
(3)构建会话工厂。通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。
(4)创建 SqlSession 对象。由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL的所有方法。
(5)MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
(6)在 Executor 接口的执行方法中,包含一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等。Mapper.xml文件中一个SQL对应一个MappedStatement对象,SQL的id即是MappedStatement的id。
(7)输入参数映射。在执行方法时,MappedStatement 对象会对用户执行 SQL 语句的输入参数进行定义(可以定义为Map、List类型、基本类型和POJO类型),Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对preparedStatement对象设置参数的过程。
(8)输出结果映射。在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进行定义(可以定义为Map和List类型、基本类型、POJO类型),Executor执行器会通过MappedStatement对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程。
思考:同学问老师,之前JDBC操作为什么做很多的setxx,和getxx的工作
你所使用的开发语言是面向对象的,你所使用的数据库是面向关系的,这两种截然不同的模式不能互相匹配,所以要做如上工作
ORM--->MyBatis也是属于一个ORM的框架
二.MyBatis的核心对象
5.1 创建工具类MyBatisUtil
SqlSessionFactory对象一旦创建,就会在整个应用运行过程中始终存在,没有理由去销毁它或者再创建它,并且在应用运行中也不建议多次创建SqlSessionFactory。因此SqlSessionFactory的最佳作用域是Application,即随着应用的生命周期一同存在。那么这种“存在于整个应用运行期间,并且同时存在一个对象实例”的模式就是所谓的单例模式,下面优化SqlSessionFactory的代码,最简单的实现方式就放在静态代码块下,以保证SqlSessionFactory对象只被创建一次,实现步骤如下所示。
public class MyBatisUtil { private static SqlSessionFactory factory; static{ try { InputStream is=Resources.getResourceAsStream("mybatis-config.xml"); factory=new SqlSessionFactoryBuilder().build(is); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession createSqlSession(){ return factory.openSession(false); } public static void closeSqlSession(SqlSession sqlSession){ if(sqlSession!=null){ sqlSession.close(); } } } |
5.2 SqlSession的两种使用方式
-
通过SqlSession实例来直接执行已映射的SQL语句
-
基于mapper接口方式操作数据
1) 定义绑定映射语句的接口
public interface UserMapper { public List<User> getUserList(); } |
2)修改测试类
@Test public void test() throws IOException { SqlSession sqlSession=MyBatisUtil.createSqlSession(); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); List<User> users=userMapper.getUserList(); for (User user : users) { System.out.println(user); } MyBatisUtil.closeSqlSession(sqlSession); } |
注意:第一种方式是旧版本的MyBatis提供的操作方式,现在也可以正常工作;第二种方式是MyBatis官方推荐使用的,其表达方式也更加直白,代码更加清晰,类型更加安全,也不用担心易错的字符串字面值以及强制类型转换。
三.MyBatis的核心配置文件
配置文件结构
Mybatis-config.xml配置文件的元素节点是有先后顺序的,文件结构如下所示
下面重点介绍一下几个常用的元素节点
1.properties元素描述的都是外部化、可代替的属性。这些属性可以通过以下两种方式实现
1)可通过外部指定方式,即配置在典型的java属性配置文件中,并使用这些属性对配置项实现动态配置,关键代码如下所示
database.properties
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8 username=root password=java |
mybatis-config.xml
<properties resource="database.properties"></properties> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <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)直接配置为XML,使用这些属性对配置项实现动态配置,关键代码如下
mybatis-config.xml
<properties> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="java"/> </properties> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <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> |
注意:若两种方式同时使用时,resource属性值的优先级高于property子节点配置的值
2.settings元素
settings元素的作用是设置一些非常重要的选项,用于设置和改变MyBatis运行中的行为
日志是非常重要,在企业开发过程中,程序员是离不开日志的,维护人员也离不开日志
日志的分类
1.业务日志
2.错误日志
1)mybatis集成日志
这里以log4j为例来进行配置
第1步:在项目的resources目录下创建log4j.properties文件
# Global logging configuration log4j.rootLogger=DEBUG, stdout,fileAppender # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
log4j.appender.fileAppender = org.apache.log4j.FileAppender log4j.appender.fileAppender.File = g:/log.log log4j.appender.fileAppender.Append = true log4j.appender.fileAppender.Threshold = DEBUG log4j.appender.fileAppender.layout = org.apache.log4j.PatternLayout log4j.appender.fileAppender.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n |
第2步:在pom.xml文件中添加log4j的起步依赖
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> |
第3步:在mybatis-config.xml文件中进行设置
<settings> <setting name="logImpl" value="LOG4J"/> </settings> |
第4步:使用
public class AppTest { private Logger logger= Logger.getLogger(AppTest.class); @Test public void test2(){ SqlSession sqlSession= MyBatisUtil.createSqlSession(); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); List<User> all=userMapper.getUserList(); for (User user:all) { logger.info(user.getId()+" "+user.getName()+" "+user.getAge()); } } } |
安装console grep插件,并且设置,设置如下
3.typeAliases元素
typeAliases元素的作用是配置类型别名
<typeAliases> <typeAlias type="com.pojo.User" alias="user"/> </typeAliases> |
如果一个项目中有多个POJO,需要一一进行配置,比较麻烦,可以通过package的name属性直接指定包名,MyBatis会自动扫描指定包下的JavaBean,默认名称为JavaBean的非限定类名
<typeAliases> <package name="com.pojo" /> </typeAliases> |
引用的时候,如下所示
<mapper namespace="com.dao.UserMapper"> <!-- 查询用户记录数 --> <select id="getUserList" resultType="User"> select * from users </select> </mapper> |
4.连接池
1)连接池介绍
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
2)mybatis的连接池的分类
在mybatis中,我们将它的数据源dataSource分为以下三种
type的取值
pooled:使用连接池的数据源
unpooled:不使用连接池的数据源
JNDI:使用JNDI实现的数据源
使用unpooled与pooled日志对比
相应的,mybatis内部定义了实现javax.sql.DataSource接口的UnpooledDataSource、PooledDataSource类来定义UNPOOLED、POOLED类型的数据源
3)mybatis中使用unpooled配置连接池的原理分析
通过CRLT+N调出如下对话框来进行搜索
4)mybatis中使用pooled配置连接的原理分析
使用pooled方式要保证线程安全
如果空闲池有连接就直接拿出来使用
如果空闲池没有可用的连接,会查看活动池中的连接,是否已经达到最大数量
如果 活动池中的连接 没有 达到最大数量, 会创建一个新的连接
如果活动池中的连接已经达到最大数量, 会判断活动池中哪个是最先进来的(Oldest), 然后对该链接进行处理并返回