目录
- 一、 初识MySQL
- 二,基本sql语句
- 三、 JDBC
-
- 3.1数据库驱动
- 3.2 Java中建立数据库连接 以8.0版本为例
- 3.3 提取工具类
- 3.4 关于statement资源关闭的问题
- 3.6 SQL注入问题
- 3.7 事务
- 四、 数据库连接池
- 五、在ideal内连接数据库
一、 初识MySQL
1.1 数据库分类
关系型数据库:(SQL)
- MySQL,Oracle,Sql Server,DB2,SQLlite
- 通过表和表之间,行和列之间的关系进行数据的存储。
非关系型数据库:(NO SQL) not only sql
- Redis,MongoDB
- 对象存储,通过对象自身的属性来决定
DBMS(数据库管理系统)
- 数据库管理软件,科学有效地管理数据。维护和获取数据
- MySQL:关系型数据库管理系统(RDBMS)
1.1.1 MySQL简介
- 关系型数据库管理系统
- Oracle公司
- 开源数据库软件
- 体积小,速度快,下哦那个提拥有成本低
- 官网:https://www.mysql.com
二,基本sql语句
三、 JDBC
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范
JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。
3.1数据库驱动
sun公司伪了简化开发人员(在数据库上统一)地操作,提供了一个(Java操作数据库)的规范,俗称JDBC,具体的规范的实施有专门的厂商去做。对于开发人员只需要掌握JDBC的接口操作即可
3.2 Java中建立数据库连接 以8.0版本为例
JDBC的总体步骤
- 创建工程,导入jar包:
mysql-connector-java-x.xx.xx.jar
- 注册驱动
Class.forName(com.mysql.jdbc.Driver)
- 获取连接
DriverManager.getConnection(url,username,pwd)
- 定义SQL
- 获取SQL执行对象
conn.creatStatement()
- 执行SQL
executeUpdate(sql)
- 处理返回结果
- 释放资源
①写代码前必须安装对应驱动(驱动版本需要与mysql版本一致),后期可以使用maven配置
②将对应版本的驱动加入到使用数据库的moudle中(重要:如果位置不对后期会报错ClassNotFound)
③写代码
3.2.1 加载驱动 Class.forName(com.mysql.cj.jdbc.Driver)
反射加载驱动类
//JDK5以后该行代码可以省略不写,自动加载META-INF/services/java.sql.Driver中的驱动类
Class.forName(com.mysql.cj.jdbc.Driver)
该行代码的路径来源:
如果mysql和mysql驱动的版本不是8.0路径会不一样,那么此行代码也会不一样。
3.2.2 DriverManager.getConnection() 连接数据库
DriverManagerAPI详解
DriverManager是一个只有静态方法的工具类
- 作用:
1、注册驱动
2、获取数据库连接对象-静态方法getConnection()
;
- 参数一:url —— 要连接的数据库地址 固定写法不可改变
组成:
协议://主机地址:端口号(默认3306)/数据库名?参数一&参数二&参数三&参数四&...
- 参数二:username —— 要连接的用户名
- 参数三:password —— 要连接的密码
//2、用户信息和url
String url = "jdbc:mysql://localhost:3306/jdbc_Study?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false";//预编译功能默认关闭,开启需添加参数useServerPreStmts=true
String username = "root";
String pwd = "123456";
//3、连接数据库
//connection代表一个数据库连接
Connection connection = DriverManager.getConnection(url,username,pwd);
3.2.3 获得用于执行数据库操作的statement接口对象connectionName.createStatement();
ConnectionAPI详解
- 作用:
1、获取执行SQL的对象(statement)
2、管理事务
获取执行SQL的对象
- 普通SQL执行对象
Statement createStatement()
- 预编译SQL的执行SQL执行对象:防止SQL注入
PreparedStatement prepareSatatement(sql)
- 执行存储过程的对象
CallableStatement prepareCall(sql)
事务管理
操作 | MYSQL事务管理 | JDBC事务管理,Connection中的三个接口 |
---|---|---|
开启事务 | BEGIN;/START TRANSACTION | setAutoCommit(boolean autoCommit):true为自动提交事务;false为手动提交事务,即为开启事务 |
提交事务 | COMMIT; | commit() |
回滚事务 | ROLLBACK; | rollback() |
statement:执行类
作用:用于向数据库发送方SQL数据,完成堆数据库的操作
- 数据库设置自动提交
setAutoCommit(true)
- 事务提交 :
commit();
- 数据回滚:
rollback();
Java中万事万物皆对象,自然操作数据库也得通过对象来实现;
Statement statement = connection.createStatement();
3.2.4 用statement接口对象操作数据库啦! statementName.execute…
StatementAPI详解
- 作用:
1、执行SQL语句
int executeUpdate(sql):执行DML、DDL语句
(1)返回DML的影响行数(2)DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(sql):执行DDL语句
返回ResultSet结果集对象
获取执行SQL的对象
execute是所有操作的前缀,需要说明操作这里就用什么方法
executeUpdate(String sql)
:所有的对数据库进行的更新操作,如增、删、改、查、插
等都使用此方法。返回int型数字,代表修改的行数。executeQuery(String sql)
:数据库的索引查询操作,最后会返回一个类型为ResultSet
的结果集。只有查询操作有结果集
例一:查询并接收结果集,循环打印结果集
ResultSet结果集对象封装了DQL查询语句的结果。
- next():将光标从当前位置向前移一行,判断当前行是否为有效行,返回值true:有效行,当前行有数据;false:无效行,当前行无数据。
- getXxx():获取数据:参数说明:int——列的编号,从1开始;String:列的名称
//5.1 创建SQL语句对象
String SQL = "select * from student";
//5.2 执行sql并接收结果集
ResultSet resultSet1 = statement.executeQuery(SQL);
//int i = statement.executeUpdate("insert into student(id,sname,age) values(1003,\"韩桐\",20);");
//System.out.print(i);
//注意此处如果上述被注释的语句执行则resultSet1已经被释放
while (resultSet1.next()){
System.out.println("id=" + resultSet1.getObject("id")+"StudentName="+resultSet1.getString("sname"));
}
输出:
补充操作:
resultSet.beforeFirst();//移动到最前面
resultSet.afterLast();//移动到最后面
resultSet.next();//移动到下一个数据
resultSet.previous();//移动到前一行
resuleSet.absolute(int row);// 移动到指定行
例二:更新数据库——插入数据举例
int i = statement.executeUpdate("insert into student(id,sname,age) values(1004,\"韩筠\",20);");
System.out.print(i);
补充一:JDBC的批量操作
addBatch(String):添加需要批量处理的SQL语句或是参数;
executeBatch();执行批量处理语句;
clearBatch();清除批量打包
补充二:PreparedStatement对象
与Statement对象的区别:PreparedStatement可以防止SQL注入且效率更高
SQL注入
通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法
eg:对下述SQL进行注入
String name = "zhangsan";
String pwd = '123456';
String sql = "select * from users where username = '" + name +" ' and password = '"+pwd+"' ";
String name = "lisi";
String pwd = "'or '1' = '1";
String sql = "select * from users where username = '" + name and password = '"+pwd+"' ";
SQL注入成功本质也是字符串拼接
上诉用于登录的注入后的SQL能成功的原因,拼接后的SQL语句等价于
select * from users where username = 'lisi' and password =' ' or '1'='1'
此SQL语句为一个恒等式
解决SQL注入prepareStatement(sql)
方法:将敏感字符进行转译
原理:在获取PrepareStatement对象时,将sql语句发送给mysql服务器进行检查,编译(耗时步骤);执行时就不用再进行编译步骤,速度很快,如果sql模板一样,则只需要进行一次检查、编译。
开启预PrepareStatement编译功能:默认关闭,useServerPrepStmts = true
预编译动作发生再获取PrepareStatement对象的时候
步骤:编写sql->预编译->传递参数->执行
//prepareStatement()的写法
//使用?占位符代替参数
String sql = "insert into student(id,sname,age) values (?,?,?);";
//预编译SQL,先写sql,然后不执行
statement = connection.prepareStatement(sql);
//手动给参数赋值setObject(参数下标(参数位置),参数的值)
statement.setInt(1, 1008);
statement.setString(2, "刘芊");
statement.setInt(3, 20);
//执行executeUpdate(),无参数
int i = statement.executeUpdate();
3.2.5 释放资源
释放资源是必须做的,这些源是非常占用内存的,且为了避免因为异常资源无法释放,资源的释放应该使用try-catch-finally
来处理
try{
...
}catch{
...
}finally {
//6、释放连接
if (resultSet1 != null){
try {
resultSet1.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
3.3 提取工具类
以上的代码每次协议去对数据库执行操作时都要重新写一变代码,会造成代码冗余,且代码的可扩展性不强
同时为了体现Java特有的封装性,我们应该对上述代码提取工具类。且连接数据库的信息放在代码里面会造成强耦合,所以应该把jdbc的配置放在文件db.properties
里
db.properties:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc_study?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
user=root
password=123456
新建工具类JdbcUtility.class:
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* @author fuyaling
* @create 2021-09-27-{TIME}
* <p>
* 对jdbc操作进行封装
*/
public class JdbcUtility {
//通过反射得到工具类的加载器获得相应资源
private static String driver= null;
private static String url= null;
private static String name= null;
private static String pwd= null;
private String sql;
private Statement statement;
public JdbcUtility(String sql) {
this.sql = sql;
}
static {
try{
InputStream in = JdbcUtility.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(in);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
name = properties.getProperty("user");
pwd = properties.getProperty("password");
//1、驱动只用加载一次
Class.forName(driver);
}catch (IOException | ClassNotFoundException e){
e.printStackTrace();
}
}
//2、获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, name, pwd);
}
//3、释放资源
public void close(Connection connection,Statement statement,ResultSet resultSet){
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement!=null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
新建工具类的测试类JDBCUtilityTest.class:
利用Test类测试
{
@Test
public void tes1() {
Connection connection = null;
Statement statement = null;
ResultSet resultSet =null;
try {
//连接数据库
connection = JdbcUtility.getConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from student");
while (resultSet.next()){
System.out.println( "id=" + resultSet.getInt("id"));
System.out.println( "id=" + resultSet.getString("sname"));
System.out.println( "id=" + resultSet.getInt("age"));
System.out.println( "===================");
}
int i = statement.executeUpdate("insert into student(id,sname,age) values (0000,'张三',23);");
System.out.println(i+"条数据被添加");
int j = statement.executeUpdate("delete from student where id = 0000");
System.out.println(j+"条数据被删除");
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
数据库student中存数据:
输出:
id=1001
id=李雷
id=20
===================
id=1002
id=韩梅梅
id=20
===================
id=1003
id=韩桐
id=20
===================
id=1004
id=韩筠
id=20
===================
1条数据被添加
1条数据被删除
3.4 关于statement资源关闭的问题
在对使用statement对象进行操作时,对查询操作executeQuery得到的结果集的遍历操作
,如果在更新操作之后再进型,即将下图中红圈与蓝圈的代码位置对调
对调之后,执行代码会报资源已经关闭不能使用的异常:
java.sql.SQLException: Operation not allowed after ResultSet closed
查看官方文档的解释说明:
重点:
当ResultSet对应的Statemet对象被
close()关闭
,重新执行
,或用于从多个结果序列中检索下一个结果时,Result对象将自动关闭
.
在上述代码中,在resultSet的statement对象在执行查询操作后,再次被重新执行,这时候resultSet就已经被关闭,而我并没用数组变量将得到的数据存储起来,导致在一系列操作完成之后再想去遍历查询出来的数据时,相关资源已经被回收。
此时resultSet都还未close;
当statement对象再次被使用时resultSet资源关闭
如图在更新操作前直接调用close关闭resultSet会得到相同的报错信息,再次验证。
3.6 SQL注入问题
目前,所有的SQL都会存在SQL注入问题,会采用其他的statement对象的创建方式
sql注入本质是SQL的拼接
sql存在漏洞,会导致网站数据泄露
3.7 事务
要么都成功,要么都失败
ACID原则
原子性:要么全部完成,要么都不完成
一致性:总数不变
隔离性:多个进程互不干扰
持久性:一旦提交不可回滚
3.7.1隔离性产生的问题
脏读
一个事务读取了另一个事务没有提交的数据
不可重复读
在同一个事务内,重复读取表中的数据,表数据发生改变
虚读(幻读):
在一个事务内,读取到了别人插入的数据导致前后读出来的结果不一致。
3.7.2 代码实现
- 开启事务:``conn.setAutoCommit(false);关闭自动提交开启事务
- 一组业务执行完毕,提交事务
- 可以在catch语句中显示执行回滚语句
conn.rollback()
,但是程序一旦失败就会默认回滚
四、 数据库连接池
4.1 池化技术
操作数据库的过程:数据库连接----执行完毕----释放 。释放的过程是是十分浪费资源的
为啥对象不是想要就能New出来一个?主要是成本,有些对象创建的代价比较大,比如线程、tcp连接、数据库连接等对象。对于这些创建耗时较长,或者资源占用较大(占据操作系统资源。
对于线程,内存,数据库的连接对象等等,这些都是资源,程序中当你创建一个线程或者在堆上申请一块内存时,都涉及到很多系统调用,也是非常消耗CPU的,如果你的程序需要很多类似的工作线程或者需要频繁的申请释放小块内存,如果没有在这方面进行优化,那很有可能这部分代码将会成为影响你整个程序性能的瓶颈。
而对于这些对象我们会反复的重复性的使用,如果能有一个“池子”存放这些资源对象就好了,我用的时候从中取出一个即可,“池子”自身去维护这些资源对象。
于是我们总结一些,首先这些资源对象进行抽象总结
对象有如下共同特点:
1.对象创建时间长;2.对象创建需要大量资源;3.对象创建后可被重复使用。
于是设计的管理资源池应具备如下功能:
1.租用资源对象;2.归还资源对象;3.清除过期资源对象。
通过对连接或线程等资源的复用,并对复用的数量、时间等进行控制,使系统的性能和资源消耗达到最优的状态;
池化技术能够减少资源对象的创建次数,提高程序的性能,特别是在高并发下这种提高更加明显。
实际项目中,使用池化技术来解决程序性能的瓶颈。
池化技术 - 简单点来说,就是提前保存大量的资源,以备不时之需。
上述池化技术引用自文章: “池化”技术:对象,只要你想要,想要就能要!.
池化技术:准备一些预先的资源,过来就直接连接准备好的资源
4.2 数据库连接池
- 数据库连接池是一个容器,负责分配,管理数据库连接(Connection)
- 允许应用程序重复使用一个现有的数据库连接,而非一直重新创建
- 释放空闲时间超过最大空闲时间的数据库Connection来避免因为没有释放数据库连接而引起的数据库连接遗漏
- 优点:
资源重用
提升系统响应速度
表面数据库连接遗漏
以下所有的jdbcp配置都是对mysql8.0版本的
- C3P0:是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate 一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象
- Druid:阿里巴巴
要适用一个数据库连接池,需要导入相应的jar包,一般jar可以在官网下载二进制文件,也可以在配置号maven后直接在ideal内下载(此处我还没有学maven)
4.2.1使用传统的DBCP
标准接口:DataSource,官方提供的接口,由第三方组织实现此接口,功能:获取连接
Connection getConnection()
需要的jar包:commons-dbcp
,commons-pool
,可能需要commons-logging-1.2.jar
,版本尽量一致
配置文件:dbcpconfig.properties
#连接设置 这里的名字是DBCP数据源中定义的不可改改
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc_study?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true
username=root
password=123456
#初始化连接
initialSize=10
#最大连接数
maxActive=50
#最大空闲连接
maxIdIe=20
#最小空闲连接
minIdIe=20
#超时等待时间ms
maxWait=60000
#JDBC驱动建立连接时附带的连接属性,属性的格式必须为:[属性名=property]
#注意”user“与”password“两个属性会被明确地传递,因此不需要包含他们
connectionProperties=useUnicode=true;characterEncoding=UTF8
#指定由连接池所创建的自动提交(auto-commit)状态:
defaultAutoCommit=true;
#driver default 指定又连接池所创建的连接的只读(read-only)状态
#如果没有设置该值,则”setReadOnly“方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接事务的级别(TransactionIsolation)
#可用值为下列之一:(详情可见javadoc)NONE,READ_UNCOMMITTED,READ_COMMITTED,REPEATABLE_READ,SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
使用了这些数据库连接池之后,我们在项目开发中就不需要编写连接数据库的代码了
封装的工具类JdbcUtilsDBCP
与我们自定义的工具类相比DBCP数据库连接池使得我们不用再手动单独创建connection对象和加载驱动。
private static DataSource dataSource;
static {
try{
InputStream in = JdbcUtilsDBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties properties = new Properties();
properties.load(in);
//创建数据源 工厂模式--->创建对象
dataSource = BasicDataSourceFactory.createDataSource(properties);
}catch (Exception e){
e.printStackTrace();
}
}
//2、获取连接
public static Connection getConnection() throws SQLException {
//从数据源中获取连接
return dataSource.getConnection();
}
//3、释放资源
public static void close(Connection connection, Statement statement, ResultSet resultSet){
//按顺序关闭ResultSet,statement、connection
}
测试类:
@Test
public void testDBCP() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
String sql = "select * from student";
connection = JdbcUtilsDBCP.getConnection();
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.print("id=" + resultSet.getInt("id") + "\t");
System.out.print("name=" + resultSet.getString("sname") + "\t");
System.out.println("age=" + resultSet.getInt("age"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtilsDBCP.close(connection, preparedStatement, resultSet);
}
}
4.2.2 C3P0
需要的jar包:commons-dbcp
,commons-pool-java
配置文件:c3p0-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<c3p0-config>
<!--
c3p0的默认(缺省)配置
如果在代码中"ComboPooledDataSource ds = new ComboPooledDataSource(); "这样写就表示使用的是C3P0的默认配置
-->
<default-config>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_studyuseUnicode=true&characterEncoding=utf8;serverTimezone=GMT%2B8;useSSL=true</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<!--
C3P0的命名配置
如果在代码中"ComboPooledDataSource ds = new ComboPooledDataSource("MySQL"); "这样写就表示用的name是,ySQL
-->
<named-config name="MySQL">
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_study?</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
</c3p0-config>
封装的工具类
ComboPooledDataSource
与DBCP相比,c3p0的工具类进一步简化只需要再静态代码中,实例化一个ComboPooledDataSource
对象,此对象是为了用来获取连接且ComboPooledDataSource
类也是继承于DataSource
接口类的。
private static ComboPooledDataSource dataSource;
static {
try{
//配置文件写法
dataSource = new ComboPooledDataSource("MySQL");
//代码版配置不建议
//dataSource = new ComboPooledDataSource();
//dataSource.setDriverClass();
//dataSource.setUser();
//dataSource.setPassword();
//dataSource.setJdbcUrl();
//
//dataSource.setMaxPoolSize();
//dataSource.setMinPoolSize();
}catch (Exception e){
e.printStackTrace();
}
}
//获取连接,固定写法
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
//释放连接
public static void release(Connection conn, Statement statement, ResultSet resultSet){
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
4.2.3 Druid
- 德鲁伊连接池是阿里巴巴开源的数据库连接池项目
- 功能强大,性能优秀,是Java语言最好的数据库连接池之一。
实现步骤
- jar包 druid-x.x.xx.jar
- 定义配置文件
- 加载配置文件
- 获取数据库连接池对象
- 获取连接
定义配置文件
druid.properties
driverClassName=com.mysql.cj.jdbc.Driver
#URL连接数据库的URL,其中travel(以下面例子来说)为连接的数据库,后面的参数可不改但不删
url=jdbc:mysql://localhost:3306/travel?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
characterEncoding=utf-8
#安装mysql时候设置的用户与密码
username=root
password=root
#初始化物理连接的个数
initialSize=5
#最大连接池数量
maxActive=10
#获取连接时最大等待时间
maxWait=3000
#用来检测连接是否有效的sql
validationQuery=SELECT 1
#保证安全性!
testWhileIdle=true
加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream(包括模块名在内的配置文件所在的全路径))
获取数据库连接池对象
DataSource dataSource = DuridDataSourceFactory.createDataSource(prop);
获取连接
Connection connection = dataSource.getConnection();
4.3 结论
无论使用哪一个数据源,本质上都是一样的,共同点:都必须实现DataSource
接口,
并且提供getConnection()方法,最后提供释放资源的realase
方法。
拓展:了解apache,安装maven。
五、在ideal内连接数据库
第一步选择数据库
第二步连接数据库
第三步导入需要的表
查看表结构,双击打开
更新数据,双击修改数据并提交
写SQL语句
切换数据库
数据库连接失败的处理方式