MyBatis1
JDBC编程和ORM模型
JDBC回顾
- 加载驱动 导入JDBC 连接数据库的 jar 包,利 用 CLASS.forName 加载驱动;
- 获取连接 利用DriverManager 获取 Connection,然后创建 Statement;
- 执行SQL语句 利用 Statement 执行 SQL 语句并结 合 ResultSet 处理结果集映射 Java 对象;
- 关闭资源 先开后关的顺序关闭 ResultSet, Statement,Connection 等资源。
JDBC弊端
- 硬编码:SQL语句存在Java代码中,不能很好的分离数据库语句和 Java语句,造成代码不易维护;
- 代码重复度高 :量的重复代码,以 ResultSet 为例,每次都需要重复解析结果集;
- 底层技术:JDBC属于底层的技术,不支持分布式,缓存等技术,对于复杂场景的应对不好;
- SQL参数固定:SQL语句的参数固定,使得SQL语句不灵活,无法满足多变的场景。
JDBC的本质
JDBC是SUN公司制定的一套接口(interface)
目的:解耦合——>降低程序的耦合度,提高程序的扩展力
ORM模型
ORM 模型是数据库的表和简单 Java 对象(Plain Ordinary Java Object,简称 POJO就是javabean)的映射关系模型,主要解决数据库数据和 POJO 对象的相互映射。
- Java对象:POJO 对象(Plain Ordinary Java Object): 简单的 Java 对象,实际就是 普通 JavaBeans。
- 映射配置配置分为:类与数据库中表 的映射;对象与表中记录的 映射;类的属性与数据库中 表的字段的映射。
- 数据库:按照数据结构来组织、存储 和管理数据的仓库,ORM 模型中最底层的内容。
OBject Relation Mapping 对象关系映射
对象指的是面向面向对象,关系指的是数据库中的表,
例如Java语言中的POJO类与数据库模型之间的对应关系。
常见的ORM模型:
- Hibernate Hibernate 是一个全自动的ORM模型,Hibernate 可以自动生成SQL语句,自动执行。
- MyBatis MyBatis 是一款半自动的ORM模型,它支持定制化SQL、存储过程以及高级映射。
Mybatis和hibernate区别:
- Hibernate是全自动化ORM; Mybatis是半自动化ORM。
- Hibernate简化dao层,不用考虑SQL语句的编写和结果映射,重点放在业务逻辑上; Mybatis需要手写SQL语句以及结果映射。
- Hibernate是一个重量级的框架,内部生成SQL语句,反射操作太多,导致性能下降; Mybatis是一个轻量级的框架,需要自己写sql语句,有较少的反射操作。
- Hibernate 不方便做SQL优化,遇到较复杂的SQL语句需要绕过框架实现复杂, 对多字段的结构进行部分映射困难;
- Mybatis 不仅可以做SQL优化还可以SQL与Java分离,还可以自行编写映射关系, 复杂的SQL语句Mybatis效率更高
Mybatis优势: 可以进行更细致的SQL优化;容易掌握
Hibernate优势; dao层开发比mybatis简单,mybatis需要维护SQL和结果映射 hibernate数据库移植性好。
MyBatis解决了JDBC的问题
1.数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。 解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。
2.Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。 解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
3.向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。 解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
4.对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。
MyBatis简介
**为什么选择MyBatis **
- 简单易学:易于学习,易于使用,通过文档和源 代码,可以比较完全的掌握它的设计 思路和实现;
- 灵活度高:通过定制 SQL 语句,可以比较灵活的 访问数据库,获取数据;
- 功能完整:提供了连接管理,缓存支持,线程支 持,(分布式)事务管理等功能,还 提供了其他 ORM 模型的支持。
MyBatis是一款ORM模型,支持定制化SQL、存储过程以及高级映射。可以使用简单的 XML 或注解来配置和映射 原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录
- 半自动化 支持定制化SQL、存储过程以及高级映射;
- 集成方便 不仅方便 Spring 等 JavaEE 框架的集成,还与其他 ORM 模型集成也很方便。
Mybatis快速开始
导入jar包
commons-logging-1.2.jarjavassist-3.24.1-GA.jarlog4j-api-2.11.2.jarasm-7.0.jarmysql-connector-java-8.0.22.jarant-1.10.3.jarslf4j-api-1.7.26.jarcglib-3.2.10.jarslf4j-log4j12-1.7.26.jarognl-3.2.10.jarant-launcher-1.10.3.jarlog4j-1.2.17.jarmybatis-3.5.2.jarlog4j-core-2.11.2.jar
14个jar包!!!!
引入 mybatis-config.xml 配置文件
该配置文件主要是连接数据库所需的配置信息 放到src下
<?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>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mydb4?serverTimezone=GMT" />
<property name="username" value="root" />
<property name="password" value="12345678" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- 资源路径 -->
<mapper resource="mapper/Student.xml" />
</mappers>
</configuration>
引入mapper映射文件
配置 SQL语句和映射的配置文件放到mapper包下
配置文件前面不能用空格:
测试
javabean 主要作用 传递数据 不属于任何层
Student类
package bean;
import java.util.Date;
public class Student {
private int sid;
private String sname;
private Date birthday;
private String Ssex;
private int classid;
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSsex() {
return Ssex;
}
public void setSsex(String ssex) {
Ssex = ssex;
}
public int getClassid() {
return classid;
}
public void setClassid(int classid) {
this.classid = classid;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", birthday=" + birthday + ", Ssex=" + Ssex + ", classid="
+ classid + "]";
}
}
测试类Test:
package test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class Test {
public static void main(String[] args) throws IOException {
// 1.读取配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 2.生产sqlSession的工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
// 3.通过工厂生成sqlSession对象
SqlSession sqlSession = factory.openSession();
// sql
// sqlSession.insert()
// sqlSession.update()
// sqlSession.delete();
// sqlSession.selectOne();
// List<Object> list= sqlSession.selectList("select * from student");
List<Object> list = sqlSession.selectList("selectAll");
list.forEach(System.out::println);
// for (Object object : list) {
// System.out.println(object);
// }
// 4.释放资源
sqlSession.close();
}
}
测试成功:
在mybatis中 所有的id 不允许重复 不然mybatis 直接报错 就是上面的 chuangjianxuesheng
实现增删改查
导入jar包,配置文件等
项目结构和要导入的包如下:
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="jdbc.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/Student.xml" />
</mappers>
</configuration>
jdbc.properties文件:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb4?serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=12345678
log4j.properties文件:
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# 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
StudentMapper代码:
<?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="test">
<!-- 类路径 -->
<select id="selectAll" resultType="bean.Student">
select * from student
</select>
<select id="findOne" parameterType="int"
resultType="bean.Student">
<!--select * from student where sid = #{sid} -->
select * from student where sid = #{value}
</select>
<delete id="deleteById" parameterType="int">
delete from student where
sid = #{v}
</delete>
<!-- id唯一,MyBatis本质为map集合,key[id]唯一 -->
<insert id="insertStudent" parameterType="bean.Student">
<!-- sname,birthday,ssex,classid数据库中的字段名 -->
insert into student(sname,birthday,ssex,classid)
<!-- values(#{属性名} -->
values(#{sname},#{birthday},#{ssex},#{classid})
</insert>
<update id="updateStudent" parameterType="bean.Student">
update student set
sname=#{sname},
birthday=#{birthday},
ssex=#{ssex},
classid=#{classid}
where sid=#{sid}
</update>
</mapper>
创建 MyBatisUtil 类
用来创建 MyBatis的数据库SqlSession会话类
创建 SqlSession 类访问数据库:创建出 SqlSession后,利用 SqlSession访问数据库
package dao;
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;
public class DaoUtil {
static SqlSessionFactory factory = null;
static {
try {
// 1.读取配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 2.生产sqlSession的工厂
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
// 3.返回sqlSession对象
return factory.openSession();
}
public static void closeSqlSession(SqlSession sqlSession) {
// 4.释放资源
sqlSession.close();
}
}
完成增删改查功能
要与配置文件中一致
增删改 没有resulttype
只有查询有
package dao.impl;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import bean.Student;
import dao.DaoUtil;
import dao.IStudentDao;
public class StudentDaoImpl implements IStudentDao {
@Override
public int insert(Student student) {
SqlSession sqlSession = DaoUtil.getSqlSession();
int ret = sqlSession.insert("insertStudent", student);
// TODO:这里的提交或者回滚写到Service层
if (ret > 0) {
sqlSession.commit();
} else {
sqlSession.rollback();
}
DaoUtil.closeSqlSession(sqlSession);
return ret;
}
@Override
public int delete(int sid) {
SqlSession sqlSession = DaoUtil.getSqlSession();
int ret = sqlSession.delete("deleteById", sid);
// TODO:这里的提交或者回滚写到Service层
if (ret > 0) {
sqlSession.commit();
} else {
sqlSession.rollback();
}
DaoUtil.closeSqlSession(sqlSession);
return ret;
}
@Override
public int update(Student student) {
SqlSession sqlSession = DaoUtil.getSqlSession();
int ret = sqlSession.update("updateStudent", student);
// TODO:这里的提交或者回滚写到Service层
if (ret > 0) {
sqlSession.commit();
} else {
sqlSession.rollback();
}
DaoUtil.closeSqlSession(sqlSession);
return ret;
}
@Override
public Student findStudent(int sid) {
SqlSession sqlSession = DaoUtil.getSqlSession();
Student student = sqlSession.selectOne("findOne", sid);
DaoUtil.closeSqlSession(sqlSession);
return student;
}
@Override
public List<Student> findAllStudent() {
SqlSession sqlSession = DaoUtil.getSqlSession();
List<Student> list = sqlSession.selectList("selectAll");
DaoUtil.closeSqlSession(sqlSession);
return list;
}
}
测试类
package test;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import bean.Student;
import dao.IStudentDao;
import dao.impl.StudentDaoImpl;
public class Test {
public static void main(String[] args) throws IOException {
IStudentDao dao = new StudentDaoImpl();
List<Student> list = dao.findAllStudent();
list.forEach(System.out::println);
// Student student = dao.findStudent(3);
// System.out.println(student);
// int count = dao.delete(8);
// System.out.println(count);
// Student student = new Student();
// student.setSname("测试");
// student.setBirthday(new Date());
// student.setSsex("女");
// student.setClassid(1);
// student.setSid(8);
// int count = dao.insert(student);
// int count = dao.update(student);
// System.out.println(count);
}
}
全部查询:
单个查询:
添加:
删除:
修改:
MyBatis生命周期:
- SqlSessionFactoryBuilder 构造器,会根据配置信息 生成 SqlSessionFactory。 SqlSessionFactory 利用工厂模式生产 SqlSession;
- SqlSession 既可以发送 SQL 语句去 执行并返回结果,也可以 获取 Mapper 的接口;
- SQL Mapper 映射器,给出对应的 SQL 和映射规则,负责 发送 SQL 和处理结果;
- 1)读取MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
- 2)加载映射文件。映射文件即SQL 映射文件,该文件中配置了操作数据库的SQL 语句, 需要在MyBatis 配置文件mybatis-config.xml 中加载。mybatis-config.xml 文件可以 加载多个映射文件,每个文件对应数据库中的一张表。
- 3)构造会话工厂:通过MyBatis 的环境等配置信息构建会话工厂SqlSessionFactory。
- 4)创建会话对象:由会话工厂创建SqlSession 对象,该对象中包含了执行SQL 语句的 所有方法。
- 5)Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的SQL 语句,同时负责查询缓存的维护。
- 6)MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL 语句的id、参数等信息。
- 7)输入参数映射:输入参数类型可以是Map、List 等集合类型,也可以是基本数据类型 和POJO 类型。输入参数映射过程类似于JDBC 对preparedStatement 对象设置参数 的过程。 8)输出结果映射:输出结果类型可以是Map、List 等集合类型,也可以是基本数据类 型和POJO 类型。输出结果映射过程类似于JDBC 对结果集的解析过程。
总结
**什么是 ORM **
对象关系映射,用于实现面向对象编程语言里不同类型系统的数据之间的转换;
MyBatis 的优势
简单易学,灵活度高,功能完整;
MyBatis 的生命周期
SqlSessionFactoryBuilder,SqlSessionFactory,SqlSession,SQL Mapper;