JDBC初识
|字数总计:3.2k|阅读时长:13分钟|阅读量:
概述
JDBC(java database connectivity)是java访问数据库的操作规范,实质上就是一个接口,具体的实现类(数据库驱动)由各个具体的数据库厂商实现。
JDBC核心API
接口或者类 |
作用 |
DriverManager类 |
管理和注册数据库驱动(DriverManager.registerDriver)、获取数据库连接对象(DriverManager.getConnection) |
Connection接口 |
连接对象,可以创建Statement和PreparedStatement对象(con.createStatement) |
Statement接口 |
SQL语句对象,将SQL语句发送给数据库服务器 |
PreparedStatement接口 |
SQL语句对象,是Statement子接口,预编译对象,可以防止SQL注入 |
ResultSet接口 |
用于封装数据库查询的结果集,返回给客户端的java服务器。用next方法是游标。用getXxx方法获取该行不同字段结果 |
快速入门
导入驱动Jar包
新建文件夹lib,然后将Jar包放在该文件夹下,右键选择添加成library(Add as Library)
加载和注册驱动
1
| Class.forName("com.mysql.jdbc.Driver");
|
为何可以这样注册驱动?我们知道将com.mysql.jdbc.Driver
加载进内存,会自动执行给类中静态代码块。
在该类的静态代码块中有注册驱动的代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Driver extends NonRegisteringDriver implements java.sql.Driver { public Driver() throws SQLException { }
static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } }
|
注意:从JDBC3开始,目前已经普遍使用的版本,可以不用注册驱动直接使用。因为导入的驱动Jar包中META-INF文件中有对应的注册驱动配置
详解JDBC重要的API
DriverManager类
驱动管理,用于注册驱动(Class将驱动类加载,自动执行注册驱动)或者获取连接对象
获取连接对象
1
| Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "root");
|
连接数据库的 URL 地址格式
协议名:子协议://服务器或者IP地址:端口号/数据库名?参数=参数值
举例
如果默认本机3306端口可以省略localhost:3306
乱码处理
如果数据库出现乱码,可以指定参数?characterEncoding=utf8
案例1使用用户名、密码、URL 得到连接对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.itheima; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;
public class Demo2 { public static void main(String[] args) throws SQLException { String url = "jdbc:mysql://localhost:3306/day24"; Connection connection = DriverManager.getConnection(url, "root", "root"); System.out.println(connection); } }
|
案例2使用属性文件和 url 得到连接对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.itheima; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class Demo3 { public static void main(String[] args) throws SQLException { String url = "jdbc:mysql://localhost:3306/day24"; Properties info = new Properties(); info.setProperty("user","root"); info.setProperty("password","root"); Connection connection = DriverManager.getConnection(url, info); System.out.println(connection); } }
|
Connection接口
Connection 接口,具体的实现类由数据库的厂商实现,代表一个连接对象。
接口中的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
| ### Statement接口
代表语句对象,用于**发送SQL语句给服务器**,用于执行静态SQL语句并返回它生成结果的对象。
#### 接口中的方法
executeUpdate 更新
executeQuery 查询
### PreparedStatement接口
代表语句对象,用于**发送SQL语句给服务器**,这里的SQL语句参数要用?代替。用于执行**动态**SQL语句并返回它生成结果的对象。
#### 可以防止SQL注入
本质上是和服务器协调固定了SQL语句的结构,防止了SQL注入。
#### 接口中的方法
setXxx 设置?对应的参数
### ResultSet接口
结果集对象,封装了查询结果
#### 接口中的方法
##### boolean next()
游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
##### getXxx(参数) 获取数据
Xxx:代表数据类型 如: int getInt() , String getString() 参数
1. int:代表列的编号,从1开始 如: getString(1) 2. String:代表列名称。 如: getDouble("balance")
## JDBC连接数据库步骤
- 导入数据库驱动jar包 - 加载注册驱动 - 获取连接对象 - 创建语句对象statement - 定义sql,利用statement对象给数据库服务器发送执行 - 返回执行结果 - 关闭statement、connecttion、(resultSet)
## 抽取JDBC工具类 : JDBCUtils
主要是为了简化书写
### 步骤
- 定义jdbc.properties配置文件,包括```url、user、password、driver```属性 - 定义类,定义静态方法 - 定义property对象,读取配置文件属性 - 加载注册jdbc(静态代码块) - 定义获取连接对象静态方法 - 定义close方法
### 代码
```java public class JDBCUtils { private static String url; private static String user; private static String password; private static String driver; /** * 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块 */ static{ //读取资源文件,获取值。
try { //1. 创建Properties集合类。 Properties pro = new Properties();
//获取src路径下的文件的方式--->ClassLoader 类加载器 ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL res = classLoader.getResource("jdbc.properties"); String path = res.getPath(); System.out.println(path);///D:/IdeaProjects/itcast/out/production/day04_jdbc/jdbc.properties //2. 加载文件 // pro.load(new FileReader("D:\\IdeaProjects\\itcast\\day04_jdbc\\src\\jdbc.properties")); pro.load(new FileReader(path));
//3. 获取数据,赋值 url = pro.getProperty("url"); user = pro.getProperty("user"); password = pro.getProperty("password"); driver = pro.getProperty("driver"); //4. 注册驱动 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取连接 * @return 连接对象 */ public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password); }
/** * 释放资源 * @param stmt * @param conn */ public static void close(Statement stmt,Connection conn){ if( stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } }
if( conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
|
JDBCUtils使用
直接使用静态类JDBCUtils静态方法创建连接对象。最后使用该类的close关闭statement、connection、resultset对象
如果需要修改JDBCUtils配置在jdbc.properties进行修改。
案例通过查询user表,实现查询登录功能
步骤分析
- 使用JDBCUtils对象连接数据库
- 查询user数据库表,如果查询有结果,则表示成功登录
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
public boolean login(String username ,String password){ if(username == null || password == null){ return false; } Connection conn = null; Statement stmt = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); String sql = "select * from user where username = '"+username+"' and password = '"+password+"' "; stmt = conn.createStatement(); rs = stmt.executeQuery(sql);
return rs.next();
} catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.close(rs,stmt,conn); } return false; } }
|
JDBC控制事务
事务概述
一个包含多个步骤的业务,我们期望他要么全部执行成功,要么同时执行失败。
操作
- 开启事务 setAutoCommit(false)
- 成功,手动commit,提交事务
- 失败(捕获到异常),手动rollback,回滚事务
举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class JDBCDemo10 {
public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt1 = null; PreparedStatement pstmt2 = null; try { conn = JDBCUtils.getConnection(); conn.setAutoCommit(false); String sql1 = "update account set balance = balance - ? where id = ?"; String sql2 = "update account set balance = balance + ? where id = ?"; pstmt1 = conn.prepareStatement(sql1); pstmt2 = conn.prepareStatement(sql2); pstmt1.setDouble(1,500); pstmt1.setInt(2,1); pstmt2.setDouble(1,500); pstmt2.setInt(2,2); pstmt1.executeUpdate(); int i = 3/0; pstmt2.executeUpdate(); conn.commit(); } catch (Exception e) { try { if(conn != null) { conn.rollback(); } } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtils.close(pstmt1,conn); JDBCUtils.close(pstmt2,null); } } }
|
参考
1.黑马JDBC笔记
概述
数据库连接池是一个存放connection连接对象的池子(容器)。
作用
当系统初始化后,容器被创建,容器会申请一些连接对象存放在该容器中,当用户访问数据库的时候,直接从池子中申请,用完后归还到池子中去。
好处
实现
接口
标准的接口是DataSource,包含方法
- 获取连接getConnection
- 归还连接close
具体实现
一般是由数据库厂商来实现
- C3P0数据库连接池技术
- Druid(阿里巴巴提供)
快速使用
C3P0数据库连接池技术
步骤
- 导入jar包(注意要导入数据库连接池的jar包,还要导入数据库驱动jar包)
- 在src(classPath)下定义配置文件,可以配置driverName,user,password,maxSize等
- 定义一个类文件使用
ds=new ComboPooledDataSource
直接new一个连接池
- 数据库连接池直接getConnection获取连接对象
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package cn.itcast.dataSource.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException;
public class Demo1 { public static void main(String[] args) {
try { DataSource ds=new ComboPooledDataSource("other1c3p0"); Connection con = ds.getConnection(); System.out.println(con); con.close(); } catch (SQLException e) { e.printStackTrace(); }
} }
|
Druid(阿里巴巴提供)常用
步骤
- 导入jar包(注意要导入数据库连接池的jar包,还要导入数据库驱动jar包)
- 在src(classPath)下定义配置文件,可以配置driverName,user,password,maxSize等
- 定义一个类文件使用
ds=DruidDataSourceFactory.createDataSource(pro)
这里是通过工厂类来生成连接池
- 数据库连接池直接getConnection获取连接对象
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| package cn.itcast.dataSource.druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties;
public class Demo01 { public static void main(String[] args) { Properties pro=null; try { pro = new Properties(); InputStream rs = Demo01.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(rs); } catch (IOException e) { e.printStackTrace(); } try { DataSource ds = DruidDataSourceFactory.createDataSource(pro); Connection connection = ds.getConnection(); Statement statement = connection.createStatement(); String sql="SELECT * FROM emp;"; ResultSet rs = statement.executeQuery(sql); while (rs.next()){ System.out.println(rs.getString("ename"));
} } catch (Exception e) { e.printStackTrace(); } } }
|
抽取成工具类DruidUtils
功能
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| package cn.itcast.dataSource.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties;
public class DruidUtils { private static DataSource ds;
static { try { Properties pro = new Properties(); InputStream rs = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(rs); ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }
public static Connection getConnection() { try { return ds.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return null; }
public static DataSource getDataSource() { return ds; }
public static void close(ResultSet rs, Statement stmt, Connection con) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } }
public static void close(Statement stmt, Connection con) { DruidUtils.close(null, stmt, con); }
}
|
Spring JDBC(JDBCTemplate)常用
概述
Spring框架对JDBC的简单封装。提供了JDBCTemplate对象简化JDBC的开发。JDBCTemplate对象能自动close对象,极大方便了操作。
步骤
导入jar包
创建JDBCTemplate对象。参数为数据库连接池DataSource
1 2
| DataSource ds= DruidUtils.getDataSource(); JdbcTemplate tmp=new JdbcTemplate(ds);
|
调用方法来实现
- update
- query(查询,通过BeanPropertyRowMapper封装成对象列表)
- queryForObeject(查询,通过BeanPropertyRowMapper封装成对象)
- queryForMap
- queryForList
代码举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package cn.itcast.dataSource.jdbctmplate;
import cn.itcast.dataSource.domain.Emp; import cn.itcast.dataSource.utils.DruidUtils; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource; import java.util.List;
public class JDBCTemplateDemo01 { public static void main(String[] args) { DataSource ds= DruidUtils.getDataSource(); JdbcTemplate tmp=new JdbcTemplate(ds); String sql="SELECT * FROM emp where id=1001"; Emp emp = tmp.queryForObject(sql, new BeanPropertyRowMapper<>(Emp.class)); System.out.println(emp);
String sql1="SELECT * FROM emp;"; List<Emp> emps = tmp.query(sql1, new BeanPropertyRowMapper<>(Emp.class)); for (Emp emp1 : emps) { System.out.println(emp1); }
String sql2="SELECT count(id) FROM emp;"; Long num = tmp.queryForObject(sql2, Long.class); System.out.println(num);
} }
|