MyBatis框架——概念与基本用法
一、简介
1、三层体系架构
在了解什么是MyBatis框架之前,我们需要先回忆一下在软件体系结构中学习到的三层体系架构(表现层、业务层与持久层),表现层顾名思义用于向用户展现页面与信息,是与用户直接接触的,表现层采用MVC模式,即Model模型、View视图与Controller控制器;业务层将项目的业务中所有的操作封装成方法;持久层则用于建立实体类与数据路表间的映射,完成对象数据和关系数据的转换。MyBatis是持久层的框架
2、什么是MyBatis
MyBatis是一个用Java语言编写的持久层框架,其封装了JDBC的操作细节,使得开发者只需关注SQL语句本身,而无需关注注册驱动,创建连接等繁琐重复的过程。MyBatis框架使用了ORM(Object Relational Mapping)的思想来实现结果集的封装。(ORM简单说就是将数据库表与实体类及类的属性对应起来,通过操作实体类来操作数据库)
3、MyBatis的特点:
- Mybatis是半自动化的,需要自己书写SQL语句,自己定义映射
- 实现了SQL语句与代码的解耦,通过提供DAO层,将业务逻辑与数据访问逻辑分离,将SQL语句写在xml文件中统一管理和优化
4、MyBatis组件
二、MyBatis核心配置文件
核心配置文件中配置了MyBatis的一些全局信息,包含数据库连接信息以及MyBatis运行时所需要的各种特性等信息。
数据源的配置中有UNPOOLED、POOLED和JNDI三张类型,具体区以后再整理
<?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">
<!-- MyBatis核心配置文件 -->
<configuration>
<!-- 配置环境-->
<environments default="mysql">
<environment id="mysql">
<!-- 配置mysql的环境 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<!-- 配置数据库连接的基本信息 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 指定映射文件的位置,每个Mapper拥有独立的映射文件 -->
<mappers>
<mapper resource="com/lzsf/mapper/IUserMapper.xml"/>
</mappers>
</configuration>
三、MyBatis映射文件
用于配置SQL语句映射。以下是一个简单的查询语句的映射配置文件,其中mapper元素的namespace属性用于绑定一个Mapper接口,select元素用于描述一个SQL语句,resultType属性描述了SQL语句的返回类型,若需要较复杂的返回类型,我们可以使用resultMap属性,这个后面在整理。除select外,我们还可以使用insert、update、delete元素分别对应SQL语句中的insert、update与delete
<?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.lzsf.mapper.IUserMapper">
<!-- 配置查询-->
<select id="findAll" resultType="com.lzsf.domain.User">
select * from user
</select>
</mapper>
在大多数场景下,我们编写SQL语句都需要传入参数,如果传入的是简单的参数类型,可以直接使用#{},如下:
<mapper namespace="com.lzsf.mapper.IUserMapper">
<select id="login" resultType="com.lzsf.domain.User">
select * from user where usename=#{usename} and pswd=#{pswd}
</select>
</mapper>
public interface IUserMapper {
User login(@Param("usename") String usename, @Param("pswd") String pswd);
}
对于稍复杂的参数,例如一个对象,则需要使用parameterType属性,如以下代码,MyBatis会从User对象中查找usename、pswd和tel属性,并将他们的值传入SQL语句中,若User对象中不存在SQL语句中指定的参数则会抛出ReflectionException异常
<mapper namespace="com.lzsf.mapper.IUserMapper">
<insert id="addUser" parameterType="User">
insert into user values(usename,pswd,tel)
values(#{usename},#{pswd},#{tel})
</insert>
</mapper>
public interface IUserMapper {
int addUser(User user);
}
四、SqlSession与SqlSessionFactory
1、SqlSession
SqlSession是MyBatis框架的关键对象,表示和数据库交互时的会话,完成必要数据库增删改查功能,是一个既可以发送SQL执行返回结果,也可以获取Mapper的接口。由于是接口,其无直接实例化,需要用SqlSessionFactory.openSession()来获取一个实例。每个线程应当拥有自己的SqlSession实例,SqlSession是线程不安全的,不能被共享。
2、SqlSessionFactory
工厂接口,使用工厂模式生成SqlSession实例,SqlSessionFactory也不可以直接实例化,需要通过SQLSessionFactoryBuilder.build()方法通过传入核心配置文件来构建一个实例。每一个MyBatis的项目都应当以一个SqlSessionFactory的实例为核心,SqlSessionFactory是线程安全的,SQLSessionFactory一旦被创建就应该在应用执行期间都存在,尽量不要重复创建,可以使用单例模式创建SqlSessionFactory
五、MyBatis的使用步骤:
1、搭建环境
-
创建实体类与Mapper接口
-
创建核心配置文件
-
创建映射文件
2、读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
3、创建SQLSessionFactory工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
4、创建SQLSession
SqlSession sqlSession= factory.openSession(true);
5、创建Mapper接口的代理对象
IUserMapper userMapper = sqlSession.getMapper(IUserDao.class);
6、执行Mapper中的方法
7、释放资源
注意事项:
- 映射文件与DAO接口的命名没有强制要求,我们可以将它们命名为IUserDao或IUserMapper,通常用Mapper命名较为常见
- 映射文件的位置必须与Mapper接口的包结构相同
- 映射文件中的namespace属性必须是对应的Mapper接口的全限定名
- 映射文件中的SQL语句的id属性值必须是Mapper接口中的方法名
六、一个简单的实例
读取数据库中的所有数据
项目结构:
实体类:
package com.lzsf.domain;
import java.io.Serializable;
import java.sql.Date;
public class User implements Serializable {
private Integer id;
public User(Integer id) {
this.id = id;
}
private String usename;
public String getPswd() {
return pswd;
}
public void setPswd(String pswd) {
this.pswd = pswd;
}
private String pswd;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsename() {
return usename;
}
public void setUsename(String usename) {
this.usename = usename;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", usename='" + usename + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserMapper接口
public interface IUserMapper {
List<User> findAll();
}
核心配置文件
<?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">
<!-- MyBatis核心配置文件 -->
<configuration>
<!-- 配置环境-->
<environments default="mysql">
<environment id="mysql">
<!-- 配置mysql的环境 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<!-- 配置数据库连接的基本信息 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 指定映射文件的位置,每个DAO拥有独立的映射文件 -->
<mappers>
<mapper resource="com/lzsf/mapper/IUserMapper.xml"/>
</mappers>
</configuration>
映射文件
<?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.lzsf.mapper.IUserMapper">
<!-- 配置查询-->
<select id="findAll" resultType="com.lzsf.domain.User">
select * from user
</select>
</mapper>
测试类
public class MyBatisTest {
public static void main(String[] args) throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2、创建SQLSessionFactory工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3、使用工厂生产SqlSession对象,true表示开启事务自动提交
SqlSession sqlSession= factory.openSession(true);
//4、使用SQLSession创建Mapper接口的代理对象
IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);
//5、使用代理对象执行方法
List<User> users = userMapper.findAll();
for (User u:users){
System.out.println(u.toString());
}
sqlSession.close();
in.close();
}
}
运行结果:
User{id=12, usename='zhangsan', birthday=2020-03-11, sex='男', address='北京'}
User{id=15, usename='lisi', birthday=1994-05-14, sex='男', address='苏州'}