MyBatis源码及资料: https://github.com/coderZYGui/MyBatis-Study
MyBatis系列
- MyBatis — ORM思想、MyBatis概述、日志框架、OGNL
- MyBaits — MyBatis的CRUD操作、别名配置、属性配置、查询结果映射、Mapper组件、参数处理、注解开发
- MyBatis — 动态SQL、if、where、set、foreach、sql片段
- MyBatis — 对象关系映射、延迟加载、关联对象的配置选择
- MyBatis — 缓存机制、EhCache第三方缓存
- MyBatis — MyBatis Generator插件使用(配置详解)
跳转到目录
跳转到目录
什么是框架,框架从何而来,为什么使用框架?
框架( framework) :
跳转到目录
最佳实践( Best Practice) :
跳转到目录
对象关系映射(Object Relational Mapping, 简称ORM): 是一种为了解决面向对象与关系数据库存在的互不匹配的问题的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据, 将Java程序中的对象自动持久化到关系数据库中.
ORM 主要解决对象-关系的映射
面向对象概念 | 面向关系概念 |
---|---|
类 | 表 |
对象 | 表的行(记录) |
属性 | 表的列(字段) |
跳转到目录
把对象数据库的操作封装成一套API,具有操作数据库的增删改查等操作,而且具有独立性,当持久层技术层发生改变时,不用修改任何业务层代码.
跳转到目录
跳转到目录
SqISessionFactoryBuilder (构建器)
: 根据配置信息或Java代码来构建- SqlSessionFactory对象。作用:创建SqlSessionFactory对象。
SqlSessionFactory (会话工厂)
:好比是DataSource ,线程安全的,在应用运行期间不要重复创建多次,建议使用单例模式。
作用: 创建SqlSession对象
SqISession (会话)
:好比是Connection ,线程不安全的,每次使用开启新的SqlSession对象,使用完毕正常关闭,默认使用DefaultSqlSession。提供操作数据库的增删改查方法,可以调用操作方法,也可以操作Mapper组件。
Executor (执行器)
:SqlSession本身不能直接操作数据库,需要Executor来完成,该接口有两个实现:缓存执行器(缺省)、基本执行器。
MappedStatement
:映射语句封装执行语句时的信息如SQL、输入参数、输出结果
数据库增删改查功能
。负责SQL语句的生成和查询缓存的维护
。封装了JDBC的DML、DQL 操作、参数设置
。-映射语句对象,维护了一条< insertlupdateldelete|select>节点的封装
。跳转到目录
跳转到目录
通过Maven仓库
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.3version>
dependency>
跳转到目录
MyBatis 自身的配置文件有两种:
mybatis-config.xml
<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?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="1111"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/sunny/dao/UserMapper.xml"/>
mappers>
configuration>
XxxMapper.xml
, Xxx表示模型对象insert | update | delete | select
元素中去
<mapper namespace="com.sunny.dao.UserDao">
<select id="getUserList" resultType="com.sunny.domain.User">
SELECT * FROM user;
select>
<select id="getUser" resultType="com.sunny.domain.User">
SELECT * FROM user WHERE id = #{id};
select>
mapper>
跳转到目录
public class UserDaoTest {
/**
* 查询所有用户
* @throws IOException
*/
@Test
public void queryUserListTest() throws IOException {
//1. 获得sqlSession对象
// SqlSession sqlSession = MybatisUtils.getSqlSession();
//1. 从classpath路径去加载MyBatis全局配置文件:mybatis-config.xml
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2. 创建sqlSessionFactory对象,好比是DataSource
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3. 创建sqlSession对象,好比是Connection
SqlSession sqlSession = factory.openSession();
//4. 具体操作
// 执行SQL(方式一)
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
// 方式二
// List userList = sqlSession.selectList("com.sunny.dao.UserDao.getUserList");
for (User user : userList) {
System.out.println(user);
}
// 关闭sqlSession
sqlSession.close();
}
/**
* 查询id为1的用户
* @throws IOException
*/
@Test
public void queryOneUserTest() throws IOException {
// 加载全局配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 构建sqlSessionFactory工厂类对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 根据sqlSession类对象来创建SqlSession对象
SqlSession sqlSession = factory.openSession();
// sqlSession相当于Connection,来执行SQL语句
User user = sqlSession.selectOne("com.sunny.dao.UserDao.getUser", 1L);
System.out.println(user);
}
}
// sqlSessionFactory 生产 sqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
// 使用Mybatis的第一步: 获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
// 既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。
// SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
跳转到目录
参考mybatis文档: 日志
跳转到目录
System.out.println
, 日志框架可以把日志的输出和代码分离;跳转到目录
JDK-Logging : JDK1.4版本以后开始提供的一一个自带的日志库实现,太简单, 不支持占位符显示,拓展性差,使用很少。
Commons-logging : Apache提供的日志规范,需要用户可以选择第三方的日志组件作为具体实现,本身会通过动态查找的机制找出真正日志的实现库。
Log4j : Apache下功能非常丰富的日志库实现,功能强大,可以把日志输出到控制台、文件中,是出现比较早且最受欢迎日志组件。并且Log4j可以允许自定义日志格式和日志等级,帮助开发人员全方位的掌控日志信息。
Log4j2 :是Log4j的升级,基本上把Log4j版本的核心全部重构,而且基于Log4j做了很多优化和升级。SLF4J :好比是Commons-logging是日志门面,本身并无日志的实现,制定了日志的规范,使用时得拷贝整合包。
Logback :由Log4j创始人设计的另-个开源日志组件,也是作为Log4j的替代者出现的。
速度和效率都比LOG4J高,而且官方是建议和SLF4j -起使用 ,Logback. sIf4j、 Log4j 都是出自同-一个人,所以默认对SLF4J无缝结合。
跳转到目录
ERROR > WARN> INFO > DEBUG > TRACE
如果设置级别为INFO ,则优先级高于等于INFO级别(如: INFO、WARN、ERROR )的日志信息将可以被输出,小于该级别的如DEBUG和TRACE将不会被输出。总结:日志级别越低,输出的日志越详细.
跳转到目录
三部分组成
跳转到目录
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>
# Global logging configuration
#设置全局的日志配置:输出Error级别,输出到控制台
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
#设置自定义的日志级别(测试类的包名com.sunny.dao)
log4j.logger.com.sunny.dao=DEBUG
# 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
// 自定义日志
private static Logger logger = Logger.getLogger(UserDaoTest.class);
@Test
public void testLogger() throws Exception{
// 如果日志输出级别为INFO,则输出
if (logger.isInfoEnabled()){
logger.info("银行转账操作");
}
if (logger.isDebugEnabled()){
logger.debug("查询数据库");
}
if (logger.isTraceEnabled()){
logger.trace("连接数据库");
}
if (logger.isTraceEnabled()){
logger.trace("执行SQL");
}
if (logger.isDebugEnabled()){
logger.debug("转账");
}
if (logger.isInfoEnabled()){
logger.info("银行转账成功");
}
}
跳转到目录
对象导航图语言(Object Graph Navigation Language),简称OGNL,是应用于Java中的一个开源的表达式语言(Expression Language),它被集成在Struts2等框架中,作用是对数据进行访问,它拥有类型转换、访问对象方法、操作集合对象等功能。
跳转到目录
SqISessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了SqlSessionFactory ,就不再需要它了。因此SqlSessionFactoryBuilder实例的最佳作用域是方法作用域(也就是局部方法变量)。你可以重用SqlSessionFactoryBuilder 来创建多个SqlSessionFactory 实例,但是最好还是不要让其一直存在以保证所有的XML解析资源开放给更重要的事情.
SqISessionFactory
SqlSessionFactory 一旦被创建就应该在应用的运行期间一-直存在,没有任何理由对它进行清除或重建。使用SqISessionFactory 的最佳实践是在应用运行期间不要重复创建多次, 多次重建SqlSessionFactory被视为一种代码"坏味道( bad smell)”.因此SqISessionFactory 的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
SqlSession
每个线程都应该有它自己的SqISession 实例。SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。绝对不能将SqlSession 实例的引用放在一个类的静态域,甚至-一个类的实例变量也不行。也绝不能将SqlSession 实例的引用放在任何类型的管理作用域中, 比如Servlet架构中的HttpSession. 如果你现在正在使用一种Web框架,要考虑SqISession放在-个和HTTP请求对象相似的作用域中。换句话说,每次收到的HTTP请求,就可以打开一个Sq|Session ,返回一个响应,就关闭它。这个关闭操作是很重要的,你应该把这个关闭操作放到finally 块中以确保每次都能执行关闭。下面的示例就是一-个确保 SqISession 关闭的标准模式:
相关MyBatis的详细使用