Mybatis【入门】
介绍Mybatis之前,先看张图
一下内容也是按照这张图的顺序进行描述的
什么是MyBatis
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation
迁移到了google code,并且改名为MyBatis。是一个基于Java的持久层框架
为什么学Mybatis?
- 目前最主流的持久层框架为hibernate与mybatis,而且国内目前情况使用Mybatis的公司比hibernate要多。
- Hibernate学习门槛不低,要精通门槛更高。门槛高在怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好Hibernate缓存与数据加载策略方面需要你的经验和能力都很强才行。国内目前前的情况精通hibernate技术大牛非常少。
- sql优化方面,Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。当然了,Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。说得更深入一些,如果有个查询要关联多张表,比如5张表,10张表时,而且,我们要取的字段只是其中几张表的部分字段。这时用hibernate时就会显得非常力不从心。就算用hibernate的sqlquery,后续的维护工作也会让人发狂。
JDBC编程回顾与存在的问题分析
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
// 通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
// 定义sql语句 ?表示占位符
String sql = "select * from user where username = ?";
// 获取预处理statement
preparedStatement = connection.prepareStatement(sql);
// 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
// 向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
// 遍历查询结果集
while (resultSet.next()) {
System.out.println(resultSet.getString("id") + " " + resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Jdbc存在的问题:
- 频繁创建和打开、关闭数据连接,太消耗资源
- Sql语句存在硬编码,不利于维护
- Sql参数设置硬编码,不利于维护
- 结果集获取与遍历复杂,存在硬编码,不利于维护,期望能够查询后返回一个java对象
Mybaits入门
搭建mybatis的开发环境
1.下载mybatis的jar包
2.在mysql中创建一张Student的表,大致如下
2.编写Mybatis的核心配置文件,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">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="com/entity/Student.xml" /><!-- 加载Student.xml的全路径 -->
</mappers>
</configuration>
3.创建实体类-POJO :Student类
package com.entity;
public class Student {
private int stuId;
private String stuName;
private int stuAge;
private String stuSex;
private String stuPhone;
private int cid;
public int getStuId() {
return stuId;
}
public void setStuId(int stuId) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public int getStuAge() {
return stuAge;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
public String getStuSex() {
return stuSex;
}
public void setStuSex(String stuSex) {
this.stuSex = stuSex;
}
public String getStuPhone() {
return stuPhone;
}
public void setStuPhone(String stuPhone) {
this.stuPhone = stuPhone;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
@Override
public String toString() {
return "Student [stuId=" + stuId + ", stuName=" + stuName + ", stuAge="
+ stuAge + ", stuSex=" + stuSex + ", stuPhone=" + stuPhone
+ ", cid=" + cid + "]";
}
}
4.创建Student实体类的sql映射文件 :Student.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:命名空间,用于隔离sql语句,后续有重要内容 -->
<mapper namespace="com.entity.Student">
<!-- 类似于 我们dao:
id:取名
resultType:指的是返回值类型
id:statement的id或者叫做sql的id
parameterType:声明输入参数的类型
parameterResult:声明输出结果的类型,应该编写pojo的全路径
#{}:输出参数的占位符,相当于jdbc的?
方法体:要执行的sql语句-->
<select id="getStuById" resultType="com.entity.Student"><!-- 通过学生id获取学生信息 -->
select * from Student where stuId=#{stuId}<!-- #{}输出参数的占位符,想当于jdbc中的? -->
</select>
<select id="getAllStu" resultType="com.entity.Student">
select * from Student
</select>
<insert id="addStu" parameterType="com.entity.Student"><!-- 参数类型是对象Student -->
insert into student values(default,#{stuName},#{stuAge},#{stuSex},#{stuPhone},#{cid})
</insert>
<update id="updateStu" parameterType="com.entity.Student">
update student set stuName=#{stuName},stuPhone=#{stuPhone},stuSex=#{stuSex} where stuId=#{stuId}
</update>
<delete id="delStuById" parameterType="int">
delete from student where stuId=#{stuId}
</delete>
</mapper>
5.创建测试类 :Test
package com.action;
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;
import com.entity.Student;
public class Test {
public static void main(String[] args) throws Exception {
//1.获取mybatis配置文件的输入流
InputStream inputStream=Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//3.通过SqlSessionFactory创建SqlSession对象
//注意:openSession方法可以带一个参数,参数类型bool类型
//表示是否开启自动提交,默认为false
SqlSession sqlSession=sqlSessionFactory.openSession(true);
//4执行映射文件中配置的sql语句
// Student stu=sqlSession.selectOne("com.entity.Student.getStuById",1);
List<Student> stuList=sqlSession.selectList("com.entity.Student.getAllStu");
for(Student stu:stuList){
System.out.println(stu);
}
// Student stu=new Student();
// stu.setStuId(8);
// stu.setStuName("lisi");
// stu.setStuPhone("22222");
// stu.setCid(1);
// stu.setStuAge(20);
// stu.setStuSex("男");
//int row=sqlSession.insert("com.entity.Student.addStu", stu);
//提交事务
//sqlSession.commit();
//int row=sqlSession.update("com.entity.Student.updateStu", stu);
// int row=sqlSession.delete("com.entity.Student.delStuById",8);
// System.out.println(row);
}
}
执行Test类的效果如下:
实现思路:
- mybatis配置
mybatis-config.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在mybatis-config.xml中加载。 - 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
- 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
- mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
- Mapped
Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped
Statement对象,sql的id即是Mapped statement的id。 - Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql前将输入的Java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。 - Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
接下来说一下Mybatis的基本要素
- MyBatis的核心对象 SqlSessionFactoryBuilder 、 SqlSessionFactory
、SqlSession - mybatis-config.xml 系统核心配置文件
- mapper.xml SQL映射文件
核心对象:
1.SqlSessionFactoryBuilder:
用过即丢,其生命周期只存在于方法体内
可重用其来创建多个 SqlSessionFactory 实例
负责构建SqlSessionFactory,并提供多个build方法的重载
2.SqlSessionFactory:
SqlSessionFactory是每个MyBatis应用的核心
作用:创建SqlSession实例
作用域:Application
生命周期与应用的生命周期相同
单例
存在于整个应用运行时,并且同时只存在一个对象实例
3.SqlSession:
包含了执行SQL所需的所有方法
对应一次数据库会话,会话结束必须关闭
线程级别,不能共享
注意:在SqlSession里可以执行多次SQL语句,但一旦关闭了SqlSession就需要重新创建
SqlSession的两种使用方式:
01.通过SqlSession实例直接运行映射的SQL语句
02.基于Mapper接口方式操作数据
mybatis-config.xml 系统核心配置文件