一、概述
JDBC(Java Database Connectivity)是Sun公司提供的一套关于数据库持久化操作的接口,我们只需要使用他们提供的API进行编程。
面向接口的编程思想:不同的数据库厂商根据JDBC接口,提供各自不同的实现,不同实现的集合就是不同的驱动。
持久化:将数据可以永久的存入磁盘中,断电后不会丢失。
二、数据库连接
连接步骤:
- 导入jdbc包
- 注册JDBC驱动程序
- 配置连接数据库配置
- 连接对象
public static Connection getConnection1() throws IOException, ClassNotFoundException, SQLException {
//1、读取配置文件基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String username = pros.getProperty("username");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
//2、加载驱动
Class.forName(driverClass);
//3、获取连接
Connection connection = DriverManager.getConnection(url, username, password);
//4、返回连接connection
return connection;
}
jdbc.properties配置文件
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root
不同数据库规范
RDBMS | JDBC驱动程序名称 | URL格式 |
MySQL | com.mysql.jdbc.Driver | jdbc:mysql://hostname/databaseName |
OEACLE | oracle.jdbc.driver.OracleDriver | jdbc:oracle:thin:@hostname:protNumber:databaseName |
DB2 | com.ibm.db2.net.DB2Driver | jdbc:db2:hostname:prot Number/ databaseName |
三种创建连接的方式
1、DriverManager.getConnection(URL, USER, PASS)
2、DriverManager.getConnection(URL)
3、DriverManager.getConnection(URL, Properties)
关闭JDBC连接
程序结束后应该对JDBC进行关闭操作,忘记关闭后,java垃圾收集器也会关闭此连接。
在finally中调用connection.close()方法。
三、JDBC工具类
我们可以自己编写有关JDBC的工具类,在使用JDBC时可以减少代码的重复编写。
获取连接:
public static Connection getConnection() throws Exception {
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
Class.forName(driverClass);
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
关闭资源conn和statement:
public static void closeResource(Connection conn,Statement ps){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
关闭coon,statement,resultSet资源:
public static void closeResource(Connection conn,Statement ps,ResultSet rs){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
四、Statement接口
在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句。Statement对象,用于执行不带参数的静态SQL语句。
1、Statement获取: connection.createStatement();
2、执行SQL语句 :
- statement.executeUpdate(sql); 只能执行:insert 、update、delete 语句
- statement.executeQuery(sql); 只能执行select 语句
3、使用结束时关流: statement.close();
五、PreparedStatement接口
通过查询API文档,发现preparedStatement接口是Statement接口的子接口
PreparedStatement表示预编译的SQL语句对象,SQL语句被预编译并存储在PreparedStatement对象中,'?'的部分在之后用setXxx(int index,Xxx value)来注入参数,进行动态的SQL编写,还可以防止SQL注入。
public static void test_Auto(){
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/db_user";
String user = "root";
String pass = "root";
Connection conn = null;
PreparedStatement ps = null;
try {
//1、加载驱动
Class.forName(driver);
//2、获取连接
conn = DriverManager.getConnection(url, user, pass);
//3、获取对象
String sql = "insert into db_user.teacher values (?,?,?)";
ps = conn.prepareStatement(sql);
//4、添加参数
ps.setInt(1,1);
ps.setNString(2,"李老师");
ps.setInt(3,28);
//5、执行SQL语句
boolean execute = ps.execute(sql);
if (execute){
System.out.println("执行成功!");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (ps != null){
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
六、数据库事务
1、事务:
保证事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。
当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;
要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。
2、在代码中体现:
- 关闭数据自动提交:conn.setAutoCommit(false);
- 在执行sql完成且成功后,进行事务提交: conn.commit();
- 若sql执行错误,在catch中添加回滚:conn.rollback();
public void testUpdateWithTx() {
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
System.out.println(conn.getAutoCommit());//true
//1.取消数据的自动提交
conn.setAutoCommit(false);
String sql1 = "update user_table set balance = balance - 100 where user = ?";
update(conn,sql1, "AA");
//模拟网络异常
System.out.println(10 / 0);
String sql2 = "update user_table set balance = balance + 100 where user = ?";
update(conn,sql2, "BB");
System.out.println("转账成功");
//2.提交数据
conn.commit();
} catch (Exception e) {
e.printStackTrace();
//3.回滚数据
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
//修改其为自动提交数据
//主要针对于使用数据库连接池的使用
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
JDBCUtils.closeResource(conn, null);
}
}
七、数据库连接池
1、传统方式连接数据库的问题
JDBC数据库使用DriverManager来进行数据库连接,每次建立连接都需要花费资源将Connection加载到内存中并验证用户名密码,使用完成后断开连接。
当同时有大量的不断的连接需求时,频繁的操作数据库连接会造成资源浪费,严重将会导致服务器崩溃。而且传统连接方式太过与僵硬,不能方便的设定一些特殊参数,
因此使用数据库连接池来解决传统数据库连接的问题。
2、数据库连接池的原理:
连接池基本的思想是在系统化初始的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等。
3、数据库连接池带来的好处:
1、资源的重复利用,降低资源开销
2、相应速度提升,直接从连接池中取出空闲连接。
3、对数据库连接可以统一进行管理,设置相应的参数,并防止资源泄露。
4、数据库连接池分类:
1、C3P0:是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate [2] 一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。
2、Druid:Druid不仅是一个数据库连接池,还包含一个ProxyDriver、一系列内置的JDBC组件库、一个SQL Parser。
3、Proxool:是一个Java SQL Driver驱动程序,提供了对选择的其它类型的驱动程序的连接池封装。可以非常简单的移植到现存的代码中,完全可配置,快速、成熟、健壮。可以透明地为现存的JDBC驱动程序增加连接池功能。
4、Jakarta DBCP:DBCP是一个依赖Jakartacommons-pool对象池机制的数据库连接池。DBCP可以直接的在应用程序中使用。
5、还有很多很多....
5、数据库连接池配置:
- maxWait:参数表示从连接池获取连接的超时等待时间,单位毫秒
- keepAlive:参数表示是否对空闲连接保活,布尔类型
- maxActive:最大连接池数量,允许的最大同时使用中的连接数。
- maxIdle:最大空闲连接
- initialSize: 初始化链接数
- .......
八、DBUtils的jar包的使用
Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。
dbutils包使用步骤:
- 导包: commos-dbutils-1.3.jar
- QueryRunner 进行对数据库的操作
- DbUtils 关闭链接等操作 : DbUtils.closeQuietly(conn);
例:
public void testInsert() {
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection3();
String sql = "insert into customers(name,email,birth)values(?,?,?)";
int insertCount = runner.update(conn, sql, "蔡徐坤","caixukun@126.com","1997-09-08");
System.out.println("添加了" + insertCount + "条记录");
} catch (SQLException e) {
e.printStackTrace();
}finally{
DbUtils.closeQuietly(conn);
}
}
org.apache.commons.dbutils.handlers包功能:
- ArrayHandler :将ResultSet中第一行的数据转化成对象数组
- ArrayListHandler将ResultSet中所有的数据转化成List,List中存放的是Object[]
- BeanHandler :将ResultSet中第一行的数据转化成类对象
- BeanListHandler :将ResultSet中所有的数据转化成List,List中存放的是类对象
- ColumnListHandler :将ResultSet中某一列的数据存成List,List中存放的是Object对象
- KeyedHandler :将ResultSet中存成映射,key为某一列对应为Map。Map中存放的是数据
- MapHandler :将ResultSet中第一行的数据存成Map映射
- MapListHandler :将ResultSet中所有的数据存成List。List中存放的是Map
- ScalarHandler :将ResultSet中一条记录的其中某一列的数据存成Object
org.apache.commons.dbutils.wrappers包功能:
- SqlNullCheckedResultSet :对ResultSet进行操作,改版里面的值
- StringTrimmedResultSet :去除ResultSet中中字段的左右空格。Trim()