1、数据库操作框架的历程
1.1 JDBC
JDBC(Java Data Base Connection,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成.JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序
优点:运行期:快捷、高效
缺点:编辑期:代码量大、繁琐异常处理、不支持数据库跨平台
jdbc核心api
- DriverManager 连接数据库
- Connection 连接数据库的抽象
- Statment 执行SQL
- ResultSet 数据结果集
实例
// 1.注册驱动
Class class1 = Class.forName("com.mysql.jdbc.Driver");
// 2.创建数据连接 DriverManager.getConnection()方法:获取数据库连接
String url = "jdbc:mysql://localhost:3306/mybatis";
String user = "root";
String password = "123456";
//3.获取连接
Connection connection = DriverManager.getConnection(url, user, password);
String sql = "SELECT * FROM EMP WHERE id=?";
//4.使用PreparedStatement 预解析sql语句,
PreparedStatement ps = connection.prepareStatement(sql);
ps.setInt(1,4);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
//自定义实体类
Emp emp = new Emp();
emp.setId(rs.getInt("id"));
emp.setUsername(rs.getString("username"));
System.out.println(emp);
}
1.2 DBUtils
DBUtils是Java编程中的数据库操作实用工具,小巧简单实用。
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
DBUtils三个核心功能介绍
- QueryRunner中提供对sql语句操作的API
- ResultSetHandler接口,用于定义select操作后,怎样封装结果集
- DBUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法
1.3 Hibernate
Hibernate 是由 Gavin King 于 2001 年创建的开放源代码的对象关系框架。它强大且高效的构建具有关系对象持久性和查询服务的 Java 应用程序。
Hibernate 将 Java 类映射到数据库表中,从Java数据类型中映射到SQL数据类型中,并把开发人员从 95% 的公共数据持续性编程工作中解放出来。
Hibernate 是传统 Java 对象和数据库服务器之间的桥梁,用来处理基于 O/R 映射机制和模式的那些对象。
优势
- Hibernate 使用 XML 文件来处理映射 Java 类别到数据库表格中,并且不用编写任何代码。
- 为在数据库中直接储存和检索 Java 对象提供简单的 APIs。
- 如果在数据库中或任何其它表格中出现变化,那么仅需要改变 XML 文件属性。
- 抽象不熟悉的 SQL 类型,并为我们提供工作中所熟悉的 Java 对象。
- Hibernate 不需要应用程序服务器来操作。
- 操控你数据库中对象复杂的关联。
- 最小化与访问数据库的智能提取策略。
- 提供简单的数据询问。
劣势
- hibernate的完全封装导致无法使用数据的一些功能。
- Hibernate的缓存问题。
- Hibernate对于代码的耦合度太高。
- Hibernate寻找bug困难。
- Hibernate批量数据操作需要大量的内存空间而且执行过程中需要的对象太多
1.4 JDBCTemplate
JdbcTemplate针对数据查询提供了多个重载的模板方法,你可以根据需要选用不同的模板方法.如果你的查询很简单,仅仅是传入相应SQL或者相关参数,然后取得一个单一的结果,那么你可以选择如下一组便利的模板方法。
优点:运行期:高效、内嵌Spring框架中、支持基于AOP的声明式事务
缺点:必须于Spring框架结合在一起使用、不支持数据库跨平台、默认没有缓存
1.5 Mybatis
MyBatis 是一款优秀的持久层框架/半自动的ORM,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
优点
- 与JDBC相比,减少了50%的代码量
- 最简单的持久化框架,简单易学
- SQL代码从程序代码中彻底分离出来,可以重用
- 提供XML标签,支持编写动态SQL
- 提供映射标签,支持对象与数据库的ORM字段关系映射
- 支持缓存、连接池、数据库移植....
缺点
- SQL语句编写工作量大,熟练度要高
- 数据库移植性比较差,如果需要切换数据库的话,SQL语句会有很大的差异
2、快速搭建Mybatis项目
2.1 创建普通的maven项目
2.2 添加pom依赖 (mybatis的核心jar包和数据库版本对应版本的驱动jar包)
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.test</groupId>
<artifactId>mybatis_helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
</project>
2.3 新建数据库和表
2.4 添加数据库表对应的POJO对象(相当于我们以前的实体类)
2.5 创建对应的Mapper接口
2.6 添加mybatis全局配置文件
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>
<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="EmpMapper.xml"/>-->
<mapper class="cn.test.mapper.EmpMapper"></mapper>
</mappers>
</configuration>
2.7 添加mapper (里面就维护所有的sql)
EmpMapper.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="cn.test.mapper.EmpMapper">
<!--
select:表示这个操作是一个查询操作
id表示的是要匹配的方法的名称
resultType:表示返回值的类型,查询操作必须要包含返回值的类型,对应返回的类型如果是POJO需要制定完整限定名
#{属性名}:表示要传递的参数的名称
-->
<select id="selectEmp" resultType="cn.test.pojo.Emp">
select * from Emp where id = #{id}
</select>
<!--增删改查操作不需要返回值,增删改返回的是影响的行数,mybatis会自动做判断-->
<insert id="insertEmp">
INSERT INTO `mybatis`.`emp` ( `username`) VALUES (#{username});
</insert>
<update id="updateEmp">
UPDATE EMP SET username=#{username} WHERE id=#{id}
</update>
<delete id="deleteEmp">
DELETE FROM emp WHERE id=#{id}
</delete>
</mapper>
2.8 编写测试类
public class MybatisTest {
SqlSessionFactory sqlSessionFactory;
@Before
public void before(){
// 根据全局配置文件创建出SqlSessionFactory
// SqlSessionFactory:负责创建SqlSession对象的工厂
// SqlSession:表示跟数据库建议的一次会话
String resource = "mybatis-config.xml";
// 将xml构建成输入流
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
//构建SqlSessionFactory :将全局配置文件和所有的mapper全部加载到Configuration
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}/**
* 基于StatementId的方式去执行SQL
* <mapper resource="EmpMapper.xml"/>
* @throws IOException
*/
@Test
public void test01() {
try (SqlSession session = sqlSessionFactory.openSession()) {
Emp emp = (Emp) session.selectOne("cn.test.pojo.EmpMapper.selectEmp", 1);
System.out.println(emp);
}
}/**
* 基于接口绑定的方式
* 1.新建数据访问层的接口: POJOMapper
* 2.添加mapper中对应的操作的方法
* 1.方法名要和mapper中对应的操作的节点的id要一致
* 2.返回类型要和mapper中对应的操作的节点的resultType要一致
* 3.mapper中对应的操作的节点的参数必须要在方法的参数中声明
* 3.Mapper.xml 中的namespace必须要和接口的完整限定名要一致
* 4.修改mybatis全局配置文件中的mappers,采用接口绑定的方式:
* <mapper class="cn.test.mapper.EmpMapper"></mapper>
* 5.一定要将mapper.xml和接口放在同一级目录中,只需要在resources新建和接口同样结构的文件夹就行了,生成就会合并在一起
*
* @throws IOException
*/
@Test
public void test02(){
// SqlSession负责执行具体的数据库操作
/**
* 给openSession设置不同的参数会给SqlSession后续的数据库操作造成不同影响
* boolean autoCommit : 可以设置事务为自动提交(因为在执行增删改的时候需要手动提交事务)
* Connection connection 将由当前环境配置的 DataSource 实例中获取 Connection 对象。
* TransactionIsolationLevel level 事务隔离级别将会使用驱动或数据源的默认设置。
* ExecutorType execType 预处理语句是否复用,是否批量处理更新。
*/
try(SqlSession sqlSession = sqlSessionFactory.openSession()){
String databaseProductName = sqlSession.getConnection().getMetaData().getDatabaseProductName();
System.out.println(databaseProductName);// Mybatis在getMapper就会给我们创建jdk动态代理
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
System.out.println(mapper.getClass());
Emp emp = mapper.SelectEmp(1);
System.out.println(emp);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 基于注解的方式
* 在接口方法上面写上对应的注解,不需要xml
*@Select("select * from emp where id=#{id}")
* 注意:
* 注解可以和xml共用, 但是不能同时存在方法对应的xml的id
*
*/
@Test
public void test03(){
try (SqlSession session = sqlSessionFactory.openSession()) {
EmpMapper mapper = session.getMapper(EmpMapper.class);
Emp emp = mapper.selectEmp(1);
System.out.println(emp);
}
}/**
* 添加
* 注意:增删改都需要提交事务
*
*/
@Test
public void insert(){
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp =new Emp();
emp.setUsername("张三");
try {
Integer result = mapper.insertEmp(emp);
sqlSession.commit();
System.out.println(result);
}
catch (Exception ex){
sqlSession.rollback();
}
finally {
sqlSession.close();
}}
}
3、问题
3.1 Mybatis之Mapper接口的实现原理
mybatis的mapper是用的jdk的动态代理,Mybatis在getMapper的时候创建的
3.2 ORM是什么?
对象关系映射(Object Relational Mapping,简称ORM)模式,是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中
3.3 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。
3.4 Mybatis都有哪些Executor执行器?它们之间的区别是什么?
mybatis有三种executor执行器
- impleexecutor执行器:在每执行一次update或select,就开启一个statement对象,用完后就关闭。
- reuseexecutor执行器:在执行update或select时以sql作为key去查找statement,有就直接使用,没有就创建,使用完毕后不关闭,放入Map<String,Statement>中,供下次使用。重复使用statement。
- batchexecutor执行器:执行update(jdbc批处理不支持select),会把所有sql添加到批处理中addbatch();等待统一批处理executorbatch();它缓存了多个statement,每一个statement都是addbatch(),后等待进行executorbatch()批处理。
作用范围:统一限制在sqlsession生命周期范围内。