版权声明:为中华之崛起而读书。转载请注明出处: https://blog.csdn.net/Kj_Gym/article/details/83619854
一、简介(本部分截取自W3CSchool Mybatis教程)
资源连接地址:https://www.w3cschool.cn/mybatis/7zy61ilv.html
(一)MyBatis
MyBatis是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
MyBatis的功能架构:
(二)我们把Mybatis的功能架构分为三层:
API接口层: 提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
数据处理层: 负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
基础支撑层: 负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。
(三)MyBatis的优缺点
优点:
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
- 解除sql与程序代码的耦合:通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
缺点:
- 编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
- SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
- 框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
- 二级缓存机制不佳
(二)一个小Demo
- 工程目录
- mybatis-config.xml,即mybatis的主配置文件(详细配置说明:https://www.w3cschool.cn/mybatis/7zy61ilv.html)
<?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="jdbc.properties"/>
<!-- 别名的配置 注释掉的这一种,对于类较多的时候麻烦。所以一般使用下面的一种按一定的规则“自动匹配”
在没有注解的情况下,会使用 Bean 的类名来作为它的别名。(不区分大小写)
比如com.kjgym.model.Student的别名就是student若有注解,则别名为其注解值。看下面的例子:
-->
<!-- <typeAliases>
<typeAlias alias="Student" type="com.kjgym.model.Student"/>
</typeAliases> -->
<typeAliases>
<package name="com.kjgym.model"/>
</typeAliases>
<!-- 开发环境的配置,一般来说至少三个环境。开发环境,测试环境,正式环境,三种环境可配置不同的数据库等 -->
<!-- default是默认的开发环境,可以在此指定相应的环境 -->
<environments default="development">
<!-- 开发环境 -->
<environment id="development">
<!-- mybatis支持两种:JDBC和MANAGED(托管)
JDBC:应用程序负责管理数据库连接的生命周期
MANAGED:应用服务器负责管理数据库可连接的生命周期(一般商业服务器才有此功能,如JBOSS,WebLogic)-->
<transactionManager type="JDBC"/>
<!-- datasource用来配置数据源 类型有:UNPOOLED, POOLED, JNDL
UNPOOLED:没有连接池,每一次数据库操作,Mybatis都会创建一个新的连接,用完后,关闭;适合小并发项目
POOLED:连接池
JNDL:使用应用服务器配置JNDL数据源获取数据库连接
-->
<dataSource type="POOLED">
<!-- 这里的name必须是小写,不然会报错 -->
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.userName}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
<!-- 测试环境 -->
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 这里的name必须是小写,不然会报错 -->
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.userName}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
<!-- 正式环境 -->
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 这里的name必须是小写,不然会报错 -->
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.userName}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers><!-- 最好选择第三种形式 多个类时自动全部扫描,比较方便 -->
<!-- <mapper resource="com/kjgym/mappers/StudentMapper.xml"/> -->
<!-- <mapper class="com.kjgym.mappers.StudentMapper"/> -->
<package name="com.kjgym.mappers"/>
</mappers>
</configuration>
- jdbc.properties连接数据库的信息
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_mybatis
jdbc.userName=root
jdbc.password=XXX
- log4j.properties,日志文件的简单配置
log4j.rootLogger = info,appender1,appender2
log4j.appender.appender1 = org.apache.log4j.ConsoleAppender
log4j.appender.appender2 = org.apache.log4j.FileAppender
log4j.appender.appender2.File = F://Eclipse_Go_Pro/FG_Mybatis/src/logFile.txt
log4j.appender.appender1.layout = org.apache.log4j.TTCCLayout
log4j.appender.appender2.layout = org.apache.log4j.TTCCLayout
- SqlSession工厂,产生SqlSession实例对象
package com.kjgym.utils;
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;
/**
* 单例模式生成SqlSession实例对象
* @author: kangjia
* @date: 2018年11月1日 下午12:46:59
*/
public class SqlSessionFacoryUtil {
private static SqlSessionFactory sessionFactory;
public static SqlSessionFactory getSessionFactory() {
if (sessionFactory == null) {
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
return sessionFactory;
}
public static SqlSession openSession() {
return getSessionFactory().openSession();
}
}
- Student类
package com.kjgym.model;
public class Student {
private int id;
private String name;
private int age;
public Student() {}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
- StudentMapper接口
package com.kjgym.mappers;
import java.util.List;
import com.kjgym.model.Student;
public interface StudentMapper {
public int add(Student student);
public List<Student> findAll();
public Student findById(Integer id);
public int update(Student student);
public int delete(Integer id);
}
- StudentMapper.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.kjgym.mappers.StudentMapper">
<!-- 自定义的返回值类型 -->
<resultMap type="student" id="StudentResult">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
</resultMap>
<insert id="add" parameterType="student">
insert into t_student values(null, #{name}, #{age})
</insert>
<update id="update" parameterType="student">
update t_student set name=#{name}, age=#{age}
where id=#{id}
</update>
<delete id="delete" parameterType="Integer">
delete from t_student where id = #{id}
</delete>
<select id="findById" parameterType="Integer" resultType="student">
select * from t_student where id= #{id}
</select>
<!-- 使用自定义的返回值类型 -->
<select id="findAll" resultMap="StudentResult">
select * from t_student
</select>
</mapper>
- StudentTest2测试类
package com.kjgym.service;
import java.util.Iterator;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.kjgym.mappers.StudentMapper;
import com.kjgym.model.Student;
import com.kjgym.utils.SqlSessionFacoryUtil;
public class StudentTest2 {
private static Logger logger = Logger.getLogger(StudentTest2.class);
private static SqlSession sqlSession = null;
private static StudentMapper studentMapper = null;
@Before
public void setUp() throws Exception {
sqlSession = SqlSessionFacoryUtil.openSession();
studentMapper = sqlSession.getMapper(StudentMapper.class);
}
@After
public void tearDown() throws Exception {
sqlSession.close();
}
@Test
public void testAdd() {
logger.info("添加学生");
Student student = new Student("kangjia", 22);
studentMapper.add(student);
sqlSession.commit();
}
@Test
public void testDelete() {
logger.info("删除学生");
studentMapper.delete(11);
sqlSession.commit();
}
@Test
public void testUpdate() {
logger.info("修改学生");
Student student = new Student(2, "kangjia222", 99);
studentMapper.update(student);
sqlSession.commit();
}
@Test
public void findById() {
logger.info("根据ID查询学生");
Student student = studentMapper.findById(1);
sqlSession.commit();
logger.info("姓名:" + student.getName() + "\t年龄:" + student.getAge());
}
@Test
public void testFindAll() {
logger.info("查询学生");
List<Student> studentList = studentMapper.findAll();
for (Iterator<Student> iterator = studentList.iterator(); iterator.hasNext();) {
Student student = (Student) iterator.next();
logger.info(student.toString());
}
}
}
- logFile.txt打印输出日志信息如下:
[main] INFO com.kjgym.service.StudentTest2 - 添加学生
[main] INFO com.kjgym.service.StudentTest2 - 删除学生
[main] INFO com.kjgym.service.StudentTest2 - 修改学生
[main] INFO com.kjgym.service.StudentTest2 - 根据ID查询学生
[main] INFO com.kjgym.service.StudentTest2 - 姓名:张三 年龄:10
[main] INFO com.kjgym.service.StudentTest2 - 查询学生
[main] INFO com.kjgym.service.StudentTest2 - Student [id=1, name=张三, age=10]
[main] INFO com.kjgym.service.StudentTest2 - Student [id=2, name=kangjia222, age=99]
[main] INFO com.kjgym.service.StudentTest2 - Student [id=3, name=kangjia, age=22]
[main] INFO com.kjgym.service.StudentTest2 - Student [id=4, name=kangjia, age=22]
[main] INFO com.kjgym.service.StudentTest2 - Student [id=5, name=kangjia, age=22]
[main] INFO com.kjgym.service.StudentTest2 - Student [id=6, name=kangjia, age=22]
[main] INFO com.kjgym.service.StudentTest2 - Student [id=7, name=kangjia, age=22]
[main] INFO com.kjgym.service.StudentTest2 - Student [id=8, name=kangjia, age=22]
[main] INFO com.kjgym.service.StudentTest2 - Student [id=9, name=kangjia, age=22]
[main] INFO com.kjgym.service.StudentTest2 - Student [id=10, name=kangjia, age=22]