说明:
(1)为什么写了本篇博客:在【SSM开发慕课书评网6:项目准备与SSM整合四:整合【logback日志】,【声明式事务】 ,【JUnit单元测试】;】中,SSM项目整合【声明式事务】时,发现以前接触的MySQL、JDBC、Mybatis、Spring JDBC中的【获取数据库连接、DataSource数据源、事务控制 】等内容,比较庞杂和容易混乱,所以想梳理一下;
(2)本篇博客尚未彻底解决的问题:
● Mybatis在查询时的事务控制,还没有彻底搞清楚;(最好的方式去看下Mybatis的手册,去寻求解释)
● 本篇博客介绍的Mybatis和Spring都是分开介绍的,至于在SSM整合的项目中,如何设置数据源,如何访问数据库,其变化还是比较大的;这些内容,将会在【 (17)SSM开发慕课书评网】也就是本专栏中给予展现;
(3)本篇博客的内容,在前面的几个专栏中都有介绍;本篇博客只是一个梳理和总结;
目录
4.2Mybatis框架,在单纯Mybatis项目中的使用; (这儿的内容,已经比较接近实际开发的状况了)
Summary:上面介绍Mybatis和Spring都是分开介绍的,在SSM整合的项目中,其变化还是比较大的。
说明:这儿的理解可能存在错误或偏差,随时修改。
1.MySQL本身;
(1)MySQL作为一款成熟和商用的数据库,我们在【(7)MySQL基础】专栏中对其进行了系统性介绍,如有需要可以随时去快速参考;
(2)这儿是直接通过SQL语言和MySQL打交道;比如我们可以在Navicat这个图形化工具中,直接使用SQL语言来和MySQL打交道;
(3)MySQL默认情况下,执行一条SQL语句之前都会为我们开启事务,等这条SQL语句执行完毕之后,MySQL会自动提交事务;
(4)但是,对于某些复杂的业务,尤其是哪些【复杂的,要么全做,要么一个也不做】的业务;我们就需要去手动控制事务了;
(5)为了能手动控制事务:在SQL中,可以通过【START TRANSACTION】开启手动控制事务,然后在后面写SQL语句就行了,然后可以通过【COMMIT 或 ROLLBACK】来提交或回滚事务;(自然,【START TRANSACTION】和【COMMIT 或 ROLLBACK】之间的SQL语句,都属于同一个事务)
2. 最初的JDBC;
(0)本部分的内容在【(9)JDBC入门】专栏中均有系统和详细的介绍,如有需要可以随时去快速参考;
(1)Java为了能够访问各种数据库,Java工程师提出了JDBC这个统一的接口和标准;然后,MySQL就提供了相应的MySQL驱动程序;这样以后,Java程序既可以通过JDBC,借助MySQL的驱动程序去访问MySQL数据库了;
(2)最初的情况:最开始的时候,如果我们不封装工具类,不使用Druid等连接池,而且没有主动关心事务控制时,那么我们在需要访问数据库的地方去加载JDBC驱动、创建数据库连接,然后才能去访问数据库;自然,此时在访问数据库的时候,不涉及主动进行事务控制的内容;
(3)创建了DbUtils工具类:后来为了方便,我们封装了一个DbUtils工具类,但仍然没有使用Druid等连接池,而且没有主动关心事务控制时;其实这儿和(2)没什么区别,只是封装一个工具类、更方便了而已;
● 这儿的DbUtils类,只有【获取Connection的方法】和【关闭Connection、ResultSet、Statement的方法】;其中不涉及主动进行事务控制的内容;
package com.imooc.jdbc.common; import java.sql.*; public class DbUtils { /** * 创建数据库连接 * @return * @throws SQLException * @throws ClassNotFoundException */ public static Connection getConnection() throws SQLException, ClassNotFoundException { //加载并注册JDBC驱动,和,创建数据库连接会产生异常; // 这儿将异常抛出,而不是捕获;在实际调用这个getConnection()方法的时候,再对这个异常捕获 Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/imooc?useSSL=false&useUincode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true", "root", "12345"); return conn; } /** * 关闭数据库连接 * 注:因为关闭方法中,在关闭前都做了判断是不是null,所以当实参是null的时候也是没问题的。即比如新增、删除、更新操作没有ResultSet,因为这儿ResultSet形参可以为null;所以,插叙,新增,删除,更新都可以调用这个方法; * @param rs:结果集对象; * @param stmt:执行SQL的Statement对象;这儿的形参是Statement类型,因为PrepareStatement是Statement的子接口,所以当实参是PrepareStatement类型的时候也没问题。 * @param conn:连接对象; */ public static void closeConnection(ResultSet rs, Statement stmt,Connection conn){ try { if (rs != null) { // 如果rs != null,代表rs被实例化了,所以这儿需要关闭一下,进行释放; rs.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if (stmt != null) { // 如果rs != null,代表stmt被实例化了,所以这儿需要关闭一下,进行释放; stmt.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if (conn != null && conn.isClosed() == false) { // conn.isClosed()==false代表这个连接还没有关闭,还正在使用中; conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
● 然后,我们在需要访问数据库的地方,直接通过DbUtils工具类去实现【获取Connection连接】和【关闭Connection、ResultSet、Statement】的功能;自然,此时在访问数据库的时候,其中同样不涉及主动进行事务控制的内容;
(4)引入了手动事务控制:但是,有点时候(增删改),手动控制事务是必需的;此时的案例还是使用(3)中介绍的DbUtils工具类,但仍然没有使用Druid等连接池,但是我们主动关心了事务控制;
可以看到,我们通过【Connection.setAutoCommit(false); 关闭自动提交,实现手动事务控制】;然后,通过【Connection.commit(),Connection.rollback()】来提交或回滚事务;
(5)引入了Druid等连接池:后来,为了提高程序执行效率,我们引入了数据库连接池(Druid,C3P0等);此时的案例使用(3)中介绍的DbUtils工具类(只利用了其中的【关闭Connection、ResultSet、Statement】的功能);但是这儿,出于【专注于介绍连接池,防止知识过多而迷糊】的目的,我们并没有主动关心事务控制;
● Druid数据库连接池:首先需要引入Druid的依赖;
然后,编写Druid的配置文件;
然后,就可以在代码中使用了,如DruidSample类:(1)加载属性文件;(2)获取DataSource数据源对象;(3)创建数据库连接。
package com.imooc.jdbc.sample; import com.alibaba.druid.pool.DruidDataSourceFactory; import com.imooc.jdbc.common.DbUtils; import javax.sql.DataSource; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Properties; /** * Druid连接池配置与使用 */ public class DruidSample { public static void main(String[] args) { //1.加载属性文件 Properties properties = new Properties(); /