DAO层的其他工具与框架
JDBC 的缺陷:
- 代码啰嗦、开发效率低
- 需要关注
Connection, preparedStatement, ResultSet
对象的创建与释放 - 对
ResultSet
的查询结果,需要自己封装为List
- 代码重复的地方多,
- 业务代码和数据库的操作混杂在一起
- 最严重的:SQL语句是硬编码在程序中的,造成了强耦合——如果要优化 SQL 语句,就需要对整个项目进行重新编译,打包。
Hibernate-数据库交互的框架(Object Relation Mapping,ORM),他将整个与 MySQL 操作有关的逻辑都封装好了。我们在编写业务的时候,不用管MySQL的具体操作。
- 随这业务逻辑便的越来越复杂,对MySQL操作语句的要求变得越来越高,而Hibernate关于MySQL的操作又是封闭的,这就带来很大不便。即:无法满足定制SQL
- 是一个全映射框架(即,每次查询默认查询所有字段),部分字段映射能做,但是很困难。
所以我们现希望:一个能支持定制化SQL,同时SQL语句也不要硬编码在Java程序中,并有着强大的功能。
原生 JDBC 的操作流程
- 获取数据库连接
- 写 SQL
- 获取
PreparedStatement
:ps= connection.preparedStatement(sql)
,将参数化的SQL语句传给数据库进行预编译。 - 填充参数:
ps.setObject(i+1, ars[i])
- 执行 sql:
ps.excute()
- 封装结果
MyBatis
MyBatis
是 SQL Mapper Framework for Java(SQL 映射框架),是一个强化版的 JDBC,即:
- SQL Mapper:
SQL
映射- 把数据库的表中的一行数据,映射成为一个 Java 对象。对这个对象的操作,就相当于操作表中的数据
Data Access Objects (DAOs)
: 数据访问- 对数据库进行增删改查。
MyBatis 底层就是对原生 JDBC 的一个简单封装。但其,将SQL硬编码在Java程序中这一部分抽取出来,改写在配置文件中。实现了 SQL 和 Java 编码分开的效果,功能边界清晰,一个专注业务,一个专注数据。
其余的步骤则封装成一个整体。
这样就完全解决了数据库优化问题,在带来了便捷性还保证了灵活性。
MyBatis 提供了哪些功能:
- 提供了创建
Connection, Statement(PreparedStatement), ResultSet
的能力,不在需要我们来创建这些对象了 - 提供了执行
sql
语句的能力,不用我们自己执行sql
- 提供了循环
sql
,把sql
查询结果转化为Java
对象,List
集合的能力 - 提供了关闭资源的能力,不用我们手动关闭了。
因此,我们只需要提供 SQL 语句。流程是:
- 提供
sql
语句 MyBatis
处理该语句- 得到
JavaBean
对象或List
集合
Hello World
基础环境搭建:
-
创建一个数据库,其内有一个
user
表,字段如下:-
id
-
name
-
password
-
address
-
phone
-
-
创建一个对应的 JavaBean:
User
-
创建
UserDAO
接口public interface UserDAO { User getUserById(Integer id); }
MyBatis 开始:
-
导入三个包:
mybatis-3.5.7.jar
mysql-connector-java-8.0.23.jar
log4j-1.2.17
:日志包,依赖于classpath
目录下的log4j.xml
。(不需要日志的话,可不用)
-
写配置:
-
第一个配置文件:
mybatis-config.xml
,其作为 MyBatis 的 全局配置文件,配置了事务管理器,和dataSource。目的是:- 指导 MyBatis 如何正确运行,比如连接向哪个数据库。
-
第二个配置文件:编写 DAO 接口的实现配置文件,相当于 DAOImpl。主要实现以下几个地方
-
1、namespace 属性:告诉 Mabits 当前配置文件用于实现哪个接口类
-
2、重写接口类中的方法,如:
<select>
标签用于重写查询类的方法,其中:- 属性:id-所实现接口中的方法名,resultType 指定返回值类型
- 方法体中的占位符用:
#{变量名}
代替。表示从传入参数中,取出变量名的值。
<?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:名称空间:写接口的全类名,相当于告诉 Mybatis,这个配置文件用于实现哪个接口类--> <mapper namespace="top.soultop.dao.UserDAO"> <!--select标签:用于定义一个查询操作. id 为接口中的方法名 resultType 指定返回值类型(查询操作必须指定) #{id} 取出传递过来的id参数值--> <!--相当于对 public User getUserById(Integer id); 方法的实现--> <select id="getUserById" resultType="top.soultop.bean.User"> select * from user where id = #{id} </select> </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.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true"/> <property name="username" value="root"/> <property name="password" value="*******"/> </dataSource> </environment> </environments> <!--引入我们自己编写的 每一个接口的 实现文件--> <mappers> <!--resource:从类目下 指出实现文件--> <mapper resource="UserDAO.xml"/> </mappers> </configuration>
-
-
-
测试:
- 先构建一个
SqlSessionFactory
,用于创建SqlSession
- 获取
SqlSession
用于操作数据库 - 获取
DAO
实现类
public class MyBatisTest { @Test public void tt() throws Exception{ // 1. 从 XML 中构建 SqlSessionFactory // SqlSession 工厂,用于创建 SqlSession对象 -- 类似于 Connection InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 2. 从 SqlSessionFactory 中获取 SqlSession(相当于getConnection()) SqlSession openSession = sqlSessionFactory.openSession(); try { //3. 获取到DAO接口的实现 UserDAO userDAOMapper = openSession.getMapper(UserDAO.class); // 可以发现,userDAOMapper 中,可以调用 UserDAO 接口的实现。 User userById = userDAOMapper.getUserById(1); System.out.println(userById); } finally { // 关闭资源 openSession.close(); } } } /** DEBUG 05-14 20:46:22,214 ==> Preparing: select * from user where id = ? (BaseJdbcLogger.java:137) 执行的sql语句 DEBUG 05-14 20:46:22,251 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:137) 参数填充过程 DEBUG 05-14 20:46:22,292 <== Total: 1 (BaseJdbcLogger.java:137) 查询结果的数量 User{id=1, name='章子怡', password='qwerty', address='Beijing', phone='13788658672'} */
- 先构建一个
流程总结
配置文件部分:
-
先写 MyBatis 的 全局配置文件,用于配置事务管理器,和 dataSource。作用是,指导 MyBatis 连接数据库的配置,及如何操作数据库
<configuration>
:数据源配置<mappers>
:引入 接口实现的 配置文件
-
为 DAO 接口编写配置文件,相当于 DAOImpl。格式如下:
<mapper namespace="top.soultop.dao.UserDAO"> <!--select标签:用于定义一个查询操作.--> <select id