框架是一款半成品软件,我们可以基于这个半成品软件继续开发,来完成我们个性化的需求!
如图:
ORM(Object Relational Mapping): 对象关系映射
指的是持久化数据和实体对象的映射模式,为了解决面向对象与关系型数据库存在的互不匹配的现象的技术。
如图:
简单说,ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写
ORM 把数据库映射成对象,具体映射关系如下图:
原始 JDBC 的操作问题分析
频繁创建和销毁数据库的连接会造成系统资源浪费从而影响系统性能
sql 语句在代码中硬编码,如果要修改 sql 语句,就需要修改 java 代码,造成代码不易维护
查询操作时,需要手动将结果集中的数据封装到实体对象中
增删改查操作需要参数时,需要手动将实体对象的数据设置到 sql 语句的占位符
原始 JDBC 的操作问题解决方案
使用数据库连接池初始化连接资源
将 sql 语句抽取到配置文件中
使用反射、内省(特殊的反射)等底层技术,将实体与表进行属性与字段的自动映射
通过分析原始jdbc操作存在的问题,以及对应的解决方案,那么在对应的解决方案在完全可以使用MyBatis替代
mybatis 是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程
mybatis通过xml或注解的方式将要执行的各种 statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句
最后mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api 打交道,就可以完成对数据库的持久化操作
MyBatis官网地址:http://www.mybatis.org/mybatis-3/
MyBatis开发步骤:
①添加MyBatis的jar包
②创建Student数据表
③编写Student实体类
④编写映射文件StudentMapper.xml
⑤编写核心文件MyBatisConfig.xml
⑥编写测试类
新建java项目:mybatis01
导入MyBatis的jar包 (在”今日资料\jar包“ 中,将jar包导入项目libs下)
package com.itheima.bean;
public class Student {
private Integer id;
private String name;
private Integer age;
//省略get个set方法
}
package com.itheima.dao;
public class StudentTest01 {
/*
查询全部
*/
@Test
public void selectAll() throws Exception{
//1.加载核心配置文件
//2.获取SqlSession工厂对象
//3.通过SqlSession工厂对象获取SqlSession对象
//4.执行映射配置文件中的sql语句,并接收结果
//5.处理结果
//6.释放资源
}
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="StudentMapper">
<select id="selectAll" resultType="com.itheima.bean.Student">
SELECT * FROM student
select>
mapper>
DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://192.168.59.143:3306/db1" />
<property name="username" value="root" />
<property name="password" value="itheima" />
dataSource>
environment>
environments>
<mappers>
<mapper resource="StudentMapper.xml"/>
mappers>
configuration>
@Test
public void selectAll() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.执行映射配置文件中的sql语句,并接收结果(参数是StudentMapper.xml中的selectAll)
List<Student> list = sqlSession.selectList("StudentMapper.selectAll");
//5.处理结果
for (Student stu : list) {
System.out.println(stu);
}
//6.释放资源
sqlSession.close();
is.close();
}
框架
框架是一款半成品软件,我们可以基于框架继续开发,从而完成一些个性化的需求。
ORM
对象关系映射,数据和实体对象的映射。
MyBatis
是一个优秀的基于 Java 的持久层框架,它内部封装了 JDBC。
org.apache.ibatis.io.Resources:加载资源的工具类
核心方法
如果不使用Resources,那我们可以自己使用类加载器(但是麻烦)
//InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
InputStream is = StudentTest01.class.getClassLoader().getResourceAsStream("MyBatisConfig.xml");
org.apache.ibatis.session.SqlSessionFactoryBuilder:获取 SqlSessionFactory 工厂对象的功能类
核心方法
通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
InputStream inputStream = Resources.getResourceAsStream("MyBatisConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory fact ory = builder.build(inputStream);
代码
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.执行映射配置文件中的sql语句,并接收结果
List<Student> list = sqlSession.selectList("StudentMapper.selectAll");
SqlSession 实例在 MyBatis 中是非常强大的一个类。在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法
作用:
本质:
映射配置文件包含了数据和对象之间的映射关系以及要执行的 SQL 语句
:查询功能标签
属性
id:唯一标识, 配合名称空间使用。
parameterType:指定参数映射的对象类型
resultType:指定结果映射的对象类型
SQL 获取参数: #{属性名}
修改StudentMapper.xml,增加如下:
测试类StudentTest01.java,新增代码:
/*
根据id查询
*/
@Test
public void selectById() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.执行映射配置文件中的sql语句,并接收结果
Student stu = sqlSession.selectOne("StudentMapper.selectById", 3);
//5.处理结果
System.out.println(stu);
//6.释放资源
sqlSession.close();
is.close();
}
:新增功能标签
属性
id:唯一标识, 配合名称空间使用
parameterType:指定参数映射的对象类型
resultType:指定结果映射的对象类型
SQL 获取参数: #{属性名}
测试类StudentTest01.java,新增代码:
/*
新增功能
*/
@Test
public void insert() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
//SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
Student stu = new Student(5,"周七",27);
int result = sqlSession.insert("StudentMapper.insert", stu);
//5.提交事务
//sqlSession.commit();
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
:修改功能标签
属性
id:唯一标识, 配合名称空间使用
parameterType:指定参数映射的对象类型
resultType:指定结果映射的对象类型
SQL 获取参数: #{属性名}
测试类StudentTest01.java,新增代码:
/*
修改功能
*/
@Test
public void update() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
Student stu = new Student(5,"周七",37);
int result = sqlSession.update("StudentMapper.update",stu);
//5.提交事务
sqlSession.commit();
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
:查询功能标签。
属性
id:唯一标识, 配合名称空间使用。
parameterType:指定参数映射的对象类型。
resultType:指定结果映射的对象类型。
SQL 获取参数: #{属性名}
修改StudentMapper.xml,增加如下:
测试类StudentTest01.java,新增代码:
/*
删除功能
*/
@Test
public void delete() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
int result = sqlSession.delete("StudentMapper.delete",5);
//5.提交事务
sqlSession.commit();
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
总结: 大家可以发现crud操作,除了标签名称以及sql语句不一样之外,其他属性参数基本一致。
核心配置文件包含了 MyBatis 最核心的设置和属性信息。如数据库的连接、事务、连接池信息等。
如下图:
DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///db1" />
<property name="username" value="root" />
<property name="password" value="root" />
dataSource>
environment>
environments>
<mappers>
<mapper resource="StudentMapper.xml"/>
mappers>
configuration>
创建:src/jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.59.143:3306/db1
username=rooot
password=itheima
修改MyBatisConfig.xml配置文件:properties标签引入外部文件
<properties resource="jdbc.properties"/>
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
:为全类名起别名的父标签。
:为全类名起别名的子标签。
属性
type:指定全类名
alias:指定别名
:为指定包下所有类起别名的子标签。(别名就是类名)
如下图:
具体如下配置:修改MyBatisConfig.xml,增加代码如下:
<typeAliases>
<typeAlias type="com.itheima.bean.Student" alias="student"/>
typeAliase>
typeAliases>
然后使用的时候就方便了,修改StudentMapper.xml中的com.itheima.bean.Student
<select id="selectAll" resultType="student">
SELECT * FROM student
select>
<select id="selectById" resultType="student" parameterType="int">
SELECT * FROM student WHERE id = #{id}
select>
<insert id="insert" parameterType="student">
INSERT INTO student VALUES (#{id},#{name},#{age})
insert>
<update id="update" parameterType="student">
UPDATE student SET name = #{name},age = #{age} WHERE id = #{id}
update>
<delete id="delete" parameterType="int">
DELETE FROM student WHERE id = #{id}
delete>
在mybatis项目中持久层就不再叫dao了,而是叫做mapper(其实都是一样的,就是换个名字)
StudentMapper接口
package com.itheima.mapper;
import com.itheima.bean.Student;
import java.util.List;
/*
持久层接口
*/
public interface StudentMapper {
//查询全部
public abstract List<Student> selectAll();
//根据id查询
public abstract Student selectById(Integer id);
//新增数据
public abstract Integer insert(Student stu);
//修改数据
public abstract Integer update(Student stu);
//删除数据
public abstract Integer delete(Integer id);
}
StudentMapperImpl实现类
package com.itheima.mapper.impl;
/*
持久层实现类
*/
public class StudentMapperImpl implements StudentMapper {
/*
查询全部
*/
@Override
public List<Student> selectAll() {
}
/*
根据id查询
*/
@Override
public Student selectById(Integer id) {
}
/*
新增功能
*/
@Override
public Integer insert(Student stu) {
}
/*
修改功能
*/
@Override
public Integer update(Student stu) {
}
/*
删除功能
*/
@Override
public Integer delete(Integer id) {
}
}
StudentService接口
package com.itheima.service;
import com.itheima.bean.Student;
import java.util.List;
/*
业务层接口
*/
public interface StudentService {
//查询全部
public abstract List<Student> selectAll();
//根据id查询
public abstract Student selectById(Integer id);
//新增数据
public abstract Integer insert(Student stu);
//修改数据
public abstract Integer update(Student stu);
//删除数据
public abstract Integer delete(Integer id);
}
StudentServiceImpl实现类
package com.itheima.service.impl;
import com.itheima.bean.Student;
import com.itheima.mapper.StudentMapper;
import com.itheima.mapper.impl.StudentMapperImpl;
import com.itheima.service.StudentService;
import java.util.List;
/*
业务层实现类
*/
public class StudentServiceImpl implements StudentService {
//创建持久层对象
private StudentMapper mapper = new StudentMapperImpl();
@Override
public List<Student> selectAll() {
return mapper.selectAll();
}
@Override
public Student selectById(Integer id) {
return mapper.selectById(id);
}
@Override
public Integer insert(Student stu) {
return mapper.insert(stu);
}
@Override
public Integer update(Student stu) {
return mapper.update(stu);
}
@Override
public Integer delete(Integer id) {
return mapper.delete(id);
}
}
StudentController测试类:
package com.itheima.controller;
import com.itheima.bean.Student;
import com.itheima.service.StudentService;
import com.itheima.service.impl.StudentServiceImpl;
import org.junit.Test;
import java.util.List;
/*
控制层测试类
*/
public class StudentController {
//创建业务层对象
private StudentService service = new StudentServiceImpl();
//查询全部功能测试
@Test
public void selectAll() {
List<Student> students = service.selectAll();
for (Student stu : students) {
System.out.println(stu);
}
}
//根据id查询功能测试
@Test
public void selectById() {
Student stu = service.selectById(3);
System.out.println(stu);
}
//新增功能测试
@Test
public void insert() {
Student stu = new Student(4,"赵六",26);
Integer result = service.insert(stu);
System.out.println(result);
}
//修改功能测试
@Test
public void update() {
Student stu = new Student(4,"赵六",16);
Integer result = service.update(stu);
System.out.println(result);
}
//删除功能测试
@Test
public void delete() {
Integer result = service.delete(4);
System.out.println(result);
}
}
package com.itheima.mapper.impl;
import com.itheima.bean.Student;
import com.itheima.mapper.StudentMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
/*
持久层实现类
*/
public class StudentMapperImpl implements StudentMapper {
/*
查询全部
*/
@Override
public List<Student> selectAll() {
List<Student> list = null;
SqlSession sqlSession = null;
InputStream is = null;
try{
//1.加载核心配置文件
is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
list = sqlSession.selectList("StudentMapper.selectAll");
} catch (Exception e) {
e.printStackTrace();
} finally {
//5.释放资源
if(sqlSession != null) {
sqlSession.close();
}
if(is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//6.返回结果
return list;
}
/*
根据id查询
*/
@Override
public Student selectById(Integer id) {
Student stu = null;
SqlSession sqlSession = null;
InputStream is = null;
try{
//1.加载核心配置文件
is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
stu = sqlSession.selectOne("StudentMapper.selectById",id);
} catch (Exception e) {
e.printStackTrace();
} finally {
//5.释放资源
if(sqlSession != null) {
sqlSession.close();
}
if(is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//6.返回结果
return stu;
}
/*
新增功能
*/
@Override
public Integer insert(Student stu) {
Integer result = null;
SqlSession sqlSession = null;
InputStream is = null;
try{
//1.加载核心配置文件
is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
result = sqlSession.insert("StudentMapper.insert",stu);
} catch (Exception e) {
e.printStackTrace();
} finally {
//5.释放资源
if(sqlSession != null) {
sqlSession.close();
}
if(is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//6.返回结果
return result;
}
/*
修改功能
*/
@Override
public Integer update(Student stu) {
Integer result = null;
SqlSession sqlSession = null;
InputStream is = null;
try{
//1.加载核心配置文件
is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
result = sqlSession.update("StudentMapper.update",stu);
} catch (Exception e) {
e.printStackTrace();
} finally {
//5.释放资源
if(sqlSession != null) {
sqlSession.close();
}
if(is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//6.返回结果
return result;
}
/*
删除功能
*/
@Override
public Integer delete(Integer id) {
Integer result = null;
SqlSession sqlSession = null;
InputStream is = null;
try{
//1.加载核心配置文件
is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
result = sqlSession.delete("StudentMapper.delete",id);
} catch (Exception e) {
e.printStackTrace();
} finally {
//5.释放资源
if(sqlSession != null) {
sqlSession.close();
}
if(is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//6.返回结果
return result;
}
}
在日常开发过程中,排查问题时难免需要输出 MyBatis 真正执行的 SQL 语句、参数、结果等信息,我们就可以借助 LOG4J 的功能来实现执行信息的输出。
使用步骤:
导入 jar 包:“01-MyBatis基础\资料\jar包\log4j-1.2.17.jar”
修改核心配置文件:MyBatisConfig.xml
<settings>
<setting name="logImpl" value="log4j"/>
settings>
在 src 下编写 LOG4J 配置文件
# Global logging configuration
# 日志的四个级别,从高到低:ERROR(错误信息) WARN(警告信息) INFO(普通信息) DEBUG(调试信息,推荐使用)
# stdout:输出到控制台
log4j.rootLogger=DEBUG, stdout
# 输出格式
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n