一、持久化与ORM
持久化是程序数据瞬时状态和持久状态间装换的过程
ORM
即对象/关系映射,是一种数据持久化技术。它在对象模型和关系型数据库之间建立起对应关系,并且提供了一种机制,通过JavaBean对象去操作数据库表中的数据,编写程序的时候,以面向对象的方式处理数据,保存数据的时候,却以关系型数据库的方式存储
ORM解决方案包含下面四个部分:
- 在持久化对象上执行基本的增、删、改、查操作
- 对持久化对象提供一种查询语言或者API
- 对象关系映射工具
- 提供与事务对象交互、执行检查、延迟加载以及其他优化功能
二、MyBatis简介
- 官方网站:http://mybatis.org
- MyBatis 本是Apache的一个开源项目iBatis, 2010年项目由Apache迁移到了Google Code,并且改名为MyBatis 。2013年11月迁移到GitHub
- MyBatis 通过实体类和SQL语句之间建立映射关系,是半自动化的ORM框架,是一款优秀的基于Java的数据持久层框架
特点:
- 基于SQL语法,简单易学
- 能了解底层封装过程,内部通过JDBC访问数据库的操作
- SQL语句封装在配置文件中,便于统一管理与维护,降低程序的耦合度
- 方便程序代码调试
1.搭建MyBatis开发环境
1.1.创建Maven工程,导入MyBatis依赖的组件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>mybatis</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>mybatis Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>mybatis</finalName>
</build>
</project>
1.2.编写MyBatis核心配置文件(mybatis-config.xml)
properties:通过外部指定的方式(database.properties),实现动态配置
settings:作用:是设置一些非常重要的设置选项,用来设置和改变MyBatis运行时的行为方式
typeAliases:作用:配置类型别名,通过与MyBatis的SQL映射文件相关联,减少输入 多余的完整类名,以简化操作。
environments:表示配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上;子元素节点:environment,但是必须指定其中一个为默认运行环境(通过default指定);每个SqlSessionFactory实例只能选择一个运行环境
mappers:
作用:映射器,定义SQL语句
须在配置中引用mapper映射文件
<?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>
<properties resource="database.properties"> </properties>
<typeAliases>
<package name="com.smbms.pojo"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"> </transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driverClassName}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mybatis/mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
创建一个database.properties用于数据库连接
driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/数据库名?useSSL=false
username = 数据库用户名
password = 数据库密码
1.3.创建实体类-POJO
import lombok.ToString;
import java.util.Date;
@Data
@ToString
public class User {
private long id;
private String userCode;
private String userName;
private String userPassword;
private int gender;
private Date birthday;
private String phone;
private String address;
private int userRole;
}
1.4.创建SQL映射文件(mapper.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="aaa">-->
<mapper namespace="com.smbms.mapper.UserMapper"> <!--namespace与接口路径保持一致--><!--使用接口-->
<!--查询总条数-->
<select id="getCount" resultType="int" >
SELECT COUNT(1) FROM SMBMS_USER
</select>
<!--插入-->
<insert id="saveUser">
INSERT INTO SMBMS_USER(USERCODE,USERNAME)
VALUES ('zhangsan','张三');
</insert>
<!--更改-->
<update id="updateUser">
UPDATE SMBMS_USER SET USERNAME='张三' WHERE ID=34
</update>
<!--删除-->
<delete id="deleteUser">
DELETE FROM SMBMS_USER WHERE ID=35
</delete>
<!--通过ID来查询某条数据-->
<select id="getUserById" resultType="com.smbms.pojo.User">
SELECT * FROM SMBMS_USER WHERE ID=1
</select>
<!--查询所有数据-->
<select id="getAllUser" resultType="com.smbms.pojo.User">
SELECT * FROM SMBMS_USER
</select>
</mapper>
1.5.创建测试类
- 读取核心配置文件mybatis-config.xml
- 创建SqlSessionFactory对象,读取配置文件
- 创建SqlSession对象
- 调用mapper文件进行数据操作
package com.smbms.test;
import com.smbms.mapper.UserMapper;
import com.smbms.pojo.User;
import com.smbms.utils.MyBatisUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserTest {
private static SqlSessionFactory factory;
private static InputStream inputStream;
static {
//1.定义mybatis核心配置文件
String path = "mybatis/mybatis-config.xml";
//2.转字节流接收
try {
inputStream = Resources.getResourceAsStream(path);
} catch (IOException e) {
throw new RuntimeException(e);
}
//3.创建SqlSessionFactory对象
factory = new SqlSessionFactoryBuilder().build(inputStream);
}
/*public static void main(String[] args) throws IOException {
//4.创建核心对象-SqlSession
SqlSession sqlSession = factory.openSession();
int count = sqlSession.selectOne("aaa.getCount");
System.out.println("该表共有" + count + "条数据");
sqlSession.close();
inputStream.close();
}*/
/*public static void main(String[] args) throws IOException {
//1.定义mybatis核心配置文件
String path = "mybatis/mybatis-config.xml";
//2.转字节流接收
InputStream inputStream = Resources.getResourceAsStream(path);
//3.创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
//4.创建核心对象-SqlSession
SqlSession sqlSession = factory.openSession();
int count = sqlSession.selectOne("aaa.getCount");
System.out.println("该表共有" + count + "条数据");
sqlSession.close();
inputStream.close();
}*/
//查询总条数
@Test
public void getCount() throws IOException {
//4.创建核心对象-SqlSession
SqlSession sqlSession = factory.openSession();
int count = sqlSession.selectOne("aaa.getCount");
System.out.println("该表共有" + count + "条数据");
sqlSession.close();
inputStream.close();
}
//插入数据
@Test
public void testInsert() throws IOException {
//4.创建核心对象-SqlSession
SqlSession sqlSession = factory.openSession();
int line = sqlSession.insert("aaa.saveUser");
System.out.println(line > 0 ? "插入成功":"插入失败");
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
//更改
@Test
public void updateUser() throws IOException {
SqlSession sqlSession = factory.openSession();
int updated = sqlSession.update("aaa.updateUser");
System.out.println(updated > 0 ? "更改成功":"更改失败");
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
//删除
@Test
public void deleteUser() throws IOException {
SqlSession sqlSession = factory.openSession();
int deleted = sqlSession.update("aaa.deleteUser");
System.out.println(deleted > 0 ? "删除成功":"删除失败");
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
//下面是使用接口的
// 查询总条数
@Test
public void getCountForMapper() throws IOException {
SqlSession sqlSession = factory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int count = userMapper.getCount();
System.out.println("该表共有" + count + "条数据");
sqlSession.close();
inputStream.close();
}
//插入
@Test
public void testInsertForMapper() throws IOException {
SqlSession sqlSession = factory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int line = userMapper.saveUser();
System.out.println(line > 0 ? "插入成功":"插入失败");
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
//更改
@Test
public void updateUserForMapper() throws IOException {
SqlSession sqlSession = factory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int updated = userMapper.updateUser();
System.out.println(updated > 0 ? "更改成功":"更改失败");
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
//删除
@Test
public void deleteUserForMapper() throws IOException {
SqlSession sqlSession = factory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int deleted = userMapper.deleteUser();
System.out.println(deleted > 0 ? "删除成功":"删除失败");
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
//通过ID来查询某条数据
@Test
public void getUserByIdForMapper() throws IOException {
SqlSession sqlSession = factory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user= userMapper.getUserById();
System.out.println(user);
sqlSession.close();
inputStream.close();
}
//查询所有数据
@Test
public void getAllUserForMapper() throws IOException {
SqlSession sqlSession = factory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.getAllUser();
userList.forEach(System.out::println);
sqlSession.close();
inputStream.close();
}
1.6.创建一个接口
package com.smbms.mapper;
import com.smbms.pojo.User;
import java.util.List;
public interface UserMapper {
int getCount();// 查询总条数
int saveUser();//插入
int updateUser();//更改
int deleteUser();//删除
User getUserById();//查询其中一条数据
List<User> getAllUser();//查询所有数据
}
2.MyBatis基本要素:
MyBatis的核心对象:SqlSessionFactoryBuilder,SqlSessionFactory,SqlSession
MyBatis-config.xml 系统核心配置文件
mapper.xml SQL映射文件
2.1.SqlSessionFactoryBuilder
用过即丢,其生命周期只存在于方法体内
可重用其来创建多个 SqlSessionFactory 实例
负责构建SqlSessionFactory,并提供多个build方法的重载
2.2.SqlSessionFactory
SqlSessionFactory是每个MyBatis应用的核心
作用:创建SqlSession实例
作用域:Application
生命周期与应用的生命周期相同
单例:存在于整个应用运行时,并且同时只存在一个对象实例
2.3.SqlSession
包含了执行SQL所需的所有方法
对应一次数据库会话,会话结束必须关闭
线程级别,不能共享
在SqlSession里可以执行多次SQL语句,但一旦关闭了SqlSession就需要重新创建
2.3.1SqlSession的两种使用方式
通过SqlSession实例直接运行映射的SQL语句
基于Mapper接口方式操作数据
MyBatis框架优缺点
优点
- 与JDBC相比,减少了50%以上的代码量
- 最简单的持久化框架,小巧并简单易学
- SQL代码从程序代码中彻底分离,可重用
- 提供XML标签,支持编写动态SQL
- 提供映射标签,支持对象与数据库的ORM字段映射
缺点
- SQL语句编写工作量大,对开发人员有一定要求
- 数据库移植性差