目录
1.认识MyBatis
1.1 MyBatis优势
1.2 MyBatis简单案例
1.3 MyBatis的核心组件
1.4 生命周期
2.案例解析
========================================================================
一、认识MyBatis
1.1 MyBatis优势
- 避免传统JDBC硬编码,支持Java代码和SQL语句分离
- POJO对象和数据库记录直接映射
- 支持动态SQL【根据不同的参数,可以拼接成不同的SQL】
1.2 MyBatis简单案例
官方文档地址:https://mybatis.org/mybatis-3/zh/getting-started.html
截取部分代码
测试类
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
使用XML构建SqlSessionFactory
mybatis-config.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>
<environments default="development">
<!-- 描述的是数据库 -->
<environment id="development">
<!-- 配置事务管理器,采用JDBC管理器方式 -->
<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="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
1.3 MyBatis的核心组件
- SqlSessionFactoryBuilder(构造器):根据配置或者代码来生成SqlSessionFactory,采用的是分布构建的Builder模式
- SqlSessionFactory(工厂接口):生产SqlSession,使用的是工厂模式
- SqlSession(会话): 可以发送SQL执行返回结果,也可以获取Mapper的接口
- SQL Mapper(映射器): 由一个Java接口和XML文件(或注解)构成
SqlSessionFactory
唯一的作用就是生产MyBatis的核心接口对象SqlSessionSqlSession
- 获取Mapper接口
- 发送SQL给数据库
- 控制数据库事务
映射器
- 描述映射规则
- 提供SQL语句,并且可以配置SQL参数类型、返回类型、缓存刷新等信息
- 配置缓存
- 提供动态SQL
MyBatis运用了动态代理技术使得接口能运行起来
用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">
<!-- namespace对应的是一个接口的全限定名,MyBatis上下文可以通过它找到对应的接口 -->
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
1.4 生命周期
- SqlSessionFactoryBuilder:只能存在于创建SqlSessinoFactory的方法中
- SqlSessionFactory:相当于数据库连接池,作用是创建SqlSession接口对象。因为MyBatis的本质就是Java对数据库的操作,所以SqlSessionFactory的生命周期存在于整个MyBatis的应用之中,所以SqlSessionFactory长期保留着。
- Session:相当于数据库连接(Connection对象),可以在一个事务里面执行多条SQL,然后通过它的commit、rollback等方法,提交或者回滚事务。所以Session存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,归还给SqlSessionFactory.所以用try…catch…finally…语句来保证其正确关闭
- Mapper:是一个接口,由SqlSession创建,最大生命周期至多和SqlSession保持一致
二、案例解析
文件 | 作用 |
---|---|
Main.java | 程序入口,拥有main方法,测试类 |
RoleMapper.java | 映射器接口 |
RoleMapper.xml | 映射器XML文件,描述映射关系、SQL等内容 |
Role.java | POJO对象 |
SqlSessionFactoryUtils.java | 一个工具类,用于创建SqlSessionFactory和获取SqlSession对象 |
log4j.properties | 日志配置文件,让后台日志数据MyBatis运行的过程日志 |
mybatis-config.xml | MyBatis配置文件 |
部分代码
log4j.properties
# 配置根Logger
log4j.rootLogger=DEBUG, stdout
log4j.logger.org.mybatis=DEBUG
# 配置日志信息输出目的地Appender及Appender选项, 输出ConsoleAppender到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# 配置日志信息的格式(布局)及格式布局选项
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C %m%n
RoleMapper.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="cn.whc.March_30.mapper.RoleMapper">
<insert id="insertRole" parameterType="role">
insert into t_role(role_name, note) values (#{roleName}, #{role})
</insert>
<delete id="deleteRole" parameterType="long">
delete from t_role where id = #{id}
</delete>
<update id="updateRole" parameterType="role">
update t_role set role_name = #{roleName}, note = #{note} where id = #{id}
</update>
<select id="getRole" parameterType="long" resultType="role">
select id, role_name as roleName,note from t_role where id = #{id}
</select>
<select id="findRoles" parameterType="string" resultType="role">
select id, role_name as roleName, note from t_role
where role_name like concat('%', #{roleName}, '%')
</select>
</mapper>
mybatis-config.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="dbconfig.properties"/>
<!--别名-->
<typeAliases>
<typeAlias alias="role" type="cn.whc.March_30.entity.Role"/>
</typeAliases>
<environments default="development">
<environment id="development">
<!--配置事务管理器,采用JDBC管理器方式-->
<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="mappers/RoleMapper.xml"/>
</mappers>
</configuration>
SqlSessionFactoryUtils构建SqlSessionFactory
public class SqlSessionFactoryUtils {
private final static Class<SqlSessionFactoryUtils> LOCK = SqlSessionFactoryUtils.class;
private static SqlSessionFactory sqlSessionFactory = null;
// 加了private关键字,使得其它代码不能通过new的方式来创建它
private SqlSessionFactoryUtils(){ }
// 我们这里的SqlSessionFactory采用的是单例模式
// 加入synchronized关键字加锁,主要是为了防止在多线程中多次实例化
// SqlSessionFactory对象,保证SqlSessionFactory的唯一性
public static SqlSessionFactory getSqlSessionFactory(){
synchronized (LOCK) {
if(sqlSessionFactory != null) {
return sqlSessionFactory;
}
String resource = "mybatis-config.xml";
InputStream inputStream;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
return sqlSessionFactory;
}
}
// 创建SqlSession对象
public static SqlSession openSqlSession(){
if(sqlSessionFactory == null) {
getSqlSessionFactory();
}
return sqlSessionFactory.openSession();
}
}
Main
public class Main {
public static void main(String[] args) {
SqlSession sqlSession = null;
try {
sqlSession = SqlSessionFactoryUtils.openSqlSession();
// 动态代理
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
// 获取id为1的角色信息
Role role = roleMapper.getRole(1L);
// 获取角色名称中带有'经'的所有角色信息
List<Role> list = roleMapper.findRoles("经");
for (Role role1 : list) {
System.out.println(role1);
}
// 删除id为2的角色信息
roleMapper.deleteRole(1L);
// sqlSession默认提交为false,要设置为true,数据库修改才生效
sqlSession.commit(true);
} finally {
if(sqlSession != null) {
sqlSession.close();
}
}
}
}
结果