JDBC基础

1 数据库驱动2 JDBC3 JDBC程序4 Statement对象5 CURD测试6 SQL注入7 PreparedStatement对象8 事务9 数据库连接池
1 数据库驱动
.png)
程序通过数据库驱动和数据库交互
2 JDBC
为了简化对(数据库的统一)操作,提供了一个(java操作数据库的)规范,简称JDBC
.png)
需要的包:
- java.sql
- javax.sql
- 数据库驱动:mysql-connector-java-5.1.47.jar
3 JDBC程序
创建测试数据库
xxxxxxxxxx1171CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;2
3USE jdbcStudy;4
5CREATE TABLE `users`(6 id INT PRIMARY KEY,7 NAME VARCHAR(40),8 PASSWORD VARCHAR(40),9 email VARCHAR(60),10 birthday DATE11);12
13INSERT INTO `users`(id,NAME,PASSWORD,email,birthday)14VALUES(1,zhansan,123456,zs@sina.com,1980-12-04),15(2,lisi,123456,lisi@sina.com,1981-12-04),16(3,wangwu,123456,wangwu@sina.com,1979-12-04)创建JAVA项目 导入数据库驱动
在项目创建lib目录并将jar包拷入,添加为Library

连接数据库测试:
x
1391/*第一个JDBC程序*/2public class jdbcFirstDemo {3 public static void main(String[] args) throws ClassNotFoundException, SQLException {4 //1.加载数据库驱动5 Class.forName("com.mysql.jdbc.Driver");//加载驱动6
7 //2.输入用户信息与URL8 //useUnicode使用Unicode编码 characterEncoding设置编码utf8 useSSL使用安全连接9 String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false";10 String username = "root";11 String password = "123456";12
13 //3.连接数据库,获得数据库对象 Connection数据库对象14 Connection connection = DriverManager.getConnection(url,username,password);15
16 //4.获得执行SQL的对象 Statement执行sql的对象17 Statement statement = connection.createStatement();18
19 //5.执行SQL20 String sqlStr = "SELECT * FROM `users`;";21
22 ResultSet resultSet = statement.executeQuery(sqlStr);//返回结果集,结果集封装全部查询的结果23
24 while (resultSet.next()){25 System.out.println("-------------------------");26 System.out.println("id=" + resultSet.getObject("id"));27 System.out.println("name=" + resultSet.getObject("NAME"));28 System.out.println("pwd=" + resultSet.getObject("PASSWORD"));29 System.out.println("email=" + resultSet.getObject("email"));30 System.out.println("birth=" + resultSet.getObject("birthday"));31 }32
33 //6.关闭连接34 resultSet.close();35 statement.close();36 connection.close();37
38 }39}总结步骤:
- 1.加载驱动
- 2.连接数据库 DriverManager
- 3.获得sql对象
- 4.获得返回结果集
- 5.释放连接
加载驱动
xxxxxxxxxx1Class.forName("com.mysql.jdbc.Driver");//加载驱动 固定写法
URL
x
1String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false";2
3// 协议://主机:端口/数据库名?参数1&参数2&... 连接数据库
x
1//DriverManager2Connection connection = DriverManager.getConnection(url,username,password);3//Connection 代表数据库,可以执行数据库级别的操作4//提交事务,设置自动提交...执行
x
1Statement statement = connection.createStatement();2//Statement执行SQL的对象3String sqlStr = "SELECT * FROM `users`";//编写SQL语句4
5statement.executeQuery(sqlStr);// 查询操作DQL,返回ResultSet6statement.executeUpdate(sqlStr);// 更新,插入,删除数据DML,返回影响的行数7statement.execute(sqlStr);//执行任何SQL 查询结果
x
131//不知道数据类型2resultSet.getObject(columnName);3//知道指定数据类型4resultSet.getString(columnName);5resultSet.getInt(columnName);6resultSet.getFloat(columnName);7resultSet.getDate(columnName);8//遍历结果集 (链表)9resultSet.beforeFirst();//移动到最前面10resultSet.afterLast();//移动到最后面11resultSet.next();//移动到下一个12resultSet.previous();//移动到前一个13resultSet.absolute(row);//移动到指定行释放资源
41//释放连接2resultSet.close();3statement.close();4connection.close();4 Statement对象
JDBC的Statement对象用于向指定数据库发送SQL语句
插入
实例:
x
1Statement statement = connection.createStatement();//创建对象2String sqlStr = "INSERT INTO `users`(`name`) VALUES('张三')";//SQL语句编写3int res = statement.executeUpdate(sqlStr);//执行SQL4if(res>0){5 System.out.println("成功插入");6}删除
实例:
x
1Statement statement = connection.createStatement();//创建对象2String sqlStr = "DELETE FROM `users` WHERE `id`=1";//SQL语句编写3int res = statement.executeUpdate(sqlStr);//执行SQL4if(res>0){5 System.out.println("成功删除");6}更新
实例:
x
1Statement statement = connection.createStatement();//创建对象2String sqlStr = "UPDATE `users` SET `name`='张三' WHERE `id`=1";//SQL语句编写3int res = statement.executeUpdate(sqlStr);//执行SQL4if(res>0){5 System.out.println("成功更新");6}查询
实例:
x
1Statement statement = connection.createStatement();//创建对象2String sqlStr = "SELECT * FROM `users`";//SQL语句编写3ResultSet resultSet = statement.executeQuery(sqlStr);//执行SQL4while(resultSet.next()){5 System.out.println(resultSet.getString(columnName));6}5 CURD测试
数据库连接配置文件db.properties
xxxxxxxxxx11driver = com.mysql.jdbc.Driver2url = jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false3username = root4password = 123456数据库连接工具类
xxxxxxxxxx1551public class jdbcUtils {2 private static String url = null;3 private static String username = null;4 private static String password = null;5
6 static {7 try{8 InputStream in = jdbcUtils.class.getClassLoader().getResourceAsStream("Config/db.properties");9 Properties properties = new Properties();10 properties.load(in);11
12 String driver = properties.getProperty("driver");13 url = properties.getProperty("url");14 username = properties.getProperty("username");15 password = properties.getProperty("password");16
17 //1.驱动只用加载一次18 Class.forName(driver);19
20 }catch (Exception e){21 e.printStackTrace();22 }23 }24
25 //获取连接26 public static Connection getConnection() throws SQLException {27 return DriverManager.getConnection(url,username,password);28 }29
30 //释放资源31 public static void release(Connection conn, Statement st, ResultSet rs){32 if (rs != null){33 try {34 rs.close();35 } catch (SQLException e) {36 e.printStackTrace();37 }38 }39 if (st != null){40 try {41 st.close();42 } catch (SQLException e) {43 e.printStackTrace();44 }45 }46 if (conn != null){47 try {48 conn.close();49 } catch (SQLException e) {50 e.printStackTrace();51 }52 }53 }54}插入
xxxxxxxxxx1231public class TestInsert {2 public static void main(String[] args) {3 Connection connection = null;4 Statement statement = null;5
6 try {7 connection = jdbcUtils.getConnection();8 //获取statement对象9 statement = connection.createStatement();10 String sqlStr = "INSERT INTO `users` (`id`,`NAME`,`PASSWORD`,`email`,`birthday`) VALUES" +"(4,'张三','123456','123123@qq.com','2000-01-01')";11 int res = statement.executeUpdate(sqlStr);12 if(res>0){13 System.out.println("插入成功");14 }15
16 } catch (SQLException e) {17 e.printStackTrace();18 } finally {19 jdbcUtils.release(connection,statement,null);20 }21 }22}更新
xxxxxxxxxx1221public class TestUpdate {2 public static void main(String[] args) {3 Connection connection = null;4 Statement statement = null;5
6 try {7 connection = jdbcUtils.getConnection();8 //获取statement对象9 statement = connection.createStatement();10 String sqlStr = "UPDATE `users` SET `NAME`='张三',email='123123@qq.com' WHERE id = 1";11 int res = statement.executeUpdate(sqlStr);12 if(res>0){13 System.out.println("修改成功");14 }15
16 } catch (SQLException e) {17 e.printStackTrace();18 } finally {19 jdbcUtils.release(connection,statement,null);20 }21 }22}删除
xxxxxxxxxx1231public class TestDelete {2 public static void main(String[] args) {3 Connection connection = null;4 Statement statement = null;5
6 try {7 connection = jdbcUtils.getConnection();8 //获取statement对象9 statement = connection.createStatement();10 String sqlStr = "DELETE FROM `users` WHERE `id`=4";11 int res = statement.executeUpdate(sqlStr);12 if(res>0){13 System.out.println("删除成功");14 }15
16 } catch (SQLException e) {17 e.printStackTrace();18 } finally {19 jdbcUtils.release(connection,statement,null);20 }21 }22}查询
xxxxxxxxxx1281public class TestQuery{2 public static void main(String[] args) {3 Connection connection = null;4 Statement statement = null;5 ResultSet resultSet = null;6
7 try {8 connection = jdbcUtils.getConnection();9
10 statement = connection.createStatement();11 String sqlStr = "SELECT * FROM `users`";12 resultSet = statement.executeQuery(sqlStr);13 while (resultSet.next()){14 System.out.println("--------------");15 System.out.println("id= " + resultSet.getInt("id"));16 System.out.println("name= " + resultSet.getString("NAME"));17 System.out.println("password= " + resultSet.getString("PASSWORD"));18 System.out.println("email= " + resultSet.getString("email"));19 System.out.println("birth= " + resultSet.getDate("birthday"));20 }21
22 } catch (SQLException e) {23 e.printStackTrace();24 } finally {25 jdbcUtils.release(connection,statement,resultSet);26 }27 }28}6 SQL注入
sql注入攻击:由于程序漏洞导致,用户输入数据时输入了恶意SQL语句导致数据库信息泄露
解决:对SQL语句关键字进行屏蔽过滤
测试:
341public class SqlInjection {2 public static void main(String[] args) {3 //login("张三","123456"); //正常登录4 login(" 'or '1=1","'or '1=1");//sql注入5 }6
7 //登录操作8 public static void login(String username,String password){9 Connection connection = null;10 Statement statement = null;11 ResultSet resultSet = null;12
13 try {14 connection = jdbcUtils.getConnection();15
16 statement = connection.createStatement();17 String sqlStr = "SELECT * FROM `users` WHERE `NAME`='"+username+"' AND `PASSWORD`='"+password+"'";18 resultSet = statement.executeQuery(sqlStr);19 while (resultSet.next()){20 System.out.println("--------------");21 System.out.println("id= " + resultSet.getInt("id"));22 System.out.println("name= " + resultSet.getString("NAME"));23 System.out.println("password= " + resultSet.getString("PASSWORD"));24 System.out.println("email= " + resultSet.getString("email"));25 System.out.println("birth= " + resultSet.getDate("birthday"));26 }27
28 } catch (SQLException e) {29 e.printStackTrace();30 } finally {31 jdbcUtils.release(connection,statement,resultSet);32 }33 }34}7 PreparedStatement对象
PreparedStatement可以防止SQL注入,效率更高
插入
x
331public class TestPreInsert {2 public static void main(String[] args) {3 Connection connection = null;4 PreparedStatement statement = null;5
6 try {7 connection = jdbcUtils.getConnection();8 //在获取statement前传入SQL语句 ?为占位符9 String sqlStr = "INSERT INTO jdbcstudy.users (id, NAME, PASSWORD, email, birthday) VALUES (?,?,?,?,?)";10
11 statement = connection.prepareStatement(sqlStr);12 //手动传参赋值13 statement.setInt(1,4);14 statement.setString(2,"张三");15 statement.setString(3,"123456");16 statement.setString(4,"123123@qq.com");17 statement.setDate(5,new java.sql.Date(new Date().getTime()));18
19 //执行20 int res = statement.executeUpdate();21 if (res>0){22 System.out.println("插入成功");23 }24
25
26 } catch (SQLException e) {27 e.printStackTrace();28 } finally {29 jdbcUtils.release(connection,statement,null);30 }31
32 }33}删除
x
301public class TestPreDelete {2 public static void main(String[] args) {3 Connection connection = null;4 PreparedStatement statement = null;5
6 try {7 connection = jdbcUtils.getConnection();8 //在获取statement前传入SQL语句 ?为占位符9 String sqlStr = "DELETE FROM jdbcstudy.users WHERE id=?";10
11 statement = connection.prepareStatement(sqlStr);12 //手动传参赋值13 statement.setInt(1,4);14
15 //执行16 int res = statement.executeUpdate();17 if (res>0){18 System.out.println("删除成功");19 }20
21
22 } catch (SQLException e) {23 e.printStackTrace();24 } finally {25 jdbcUtils.release(connection,statement,null);26 }27
28 }29}更新
x
291public class TestPreUpdate {2 public static void main(String[] args) {3 Connection connection = null;4 PreparedStatement statement = null;5
6 try {7 connection = jdbcUtils.getConnection();8 //在获取statement前传入SQL语句 ?为占位符9 String sqlStr = "UPDATE jdbcstudy.users SET NAME=? WHERE id = ?";10
11 statement = connection.prepareStatement(sqlStr);12 //手动传参赋值13 statement.setString(1,"小明");14 statement.setInt(2,1);15
16 //执行17 int res = statement.executeUpdate();18 if (res>0){19 System.out.println("更新成功");20 }21
22 } catch (SQLException e) {23 e.printStackTrace();24 } finally {25 jdbcUtils.release(connection,statement,null);26 }27
28 }29}查询
x
1public class TestPreQuery {2 public static void main(String[] args) {3 Connection connection = null;4 PreparedStatement statement = null;5 ResultSet resultSet = null;6
7 try {8 connection = jdbcUtils.getConnection();9
10 String sqlStr = "SELECT * FROM jdbcstudy.users WHERE id=?";11
12 statement = connection.prepareStatement(sqlStr);13
14 statement.setInt(1,2);15
16 resultSet = statement.executeQuery();17
18 while (resultSet.next()){19 System.out.println("id=" + resultSet.getInt("id"));20 System.out.println("name=" + resultSet.getString("NAME"));21 System.out.println("password=" + resultSet.getString("password"));22 System.out.println("email=" + resultSet.getString("email"));23 System.out.println("birth=" + resultSet.getDate("birthday"));24 }25
26 } catch (SQLException e) {27 e.printStackTrace();28 } finally {29 jdbcUtils.release(connection,statement,resultSet);30 }31 }32}prepareStatement防止SQL注入:把传递的参数当做字符,特殊字符就会被转义而不是拼接字符串
8 事务
ACID原则:原子性,一致性,隔离性,持久性
- 原子性:一个事务包含的步骤,要不都完成要不都失败,不存在中间态
- 一致性:数据库操作数据符合运算规则
- 隔离性:多个事务同时执行互相不干扰
- 持久性:一但提交数据持久化到数据库,不可逆
隔离性问题:
- 脏读:一个事务读取另一个事务没有提交的值
- 不可重复读:在同一个事务内,重复读取表中的数据,表数据发生改变
- 幻读:在一个事务内读取到别的事务插入的数据
程序模拟:
x
1public class TestTransaction {2 public static void main(String[] args) {3 TransferAccount(200,"a","b");4 }5
6 public static void TransferAccount(int money, String a, String b){7 Connection connection = null;8 PreparedStatement statement = null;9
10 try {11 connection = jdbcUtils.getConnection();12 //关闭自动提交 自动开启事务13 connection.setAutoCommit(false);14
15 String sqlStr1 = "UPDATE account SET money = money-? WHERE name = ?";16 statement = connection.prepareStatement(sqlStr1);17 statement.setInt(1,money);18 statement.setString(2,a);19 int res1 = statement.executeUpdate();20 if (res1>0){21 System.out.println("扣款完成");22 }else {23 throw new Exception("更新失败,扣款失败");24 }25
26 String sqlStr2 = "UPDATE account SET money = money+? WHERE name = ?";27 statement = connection.prepareStatement(sqlStr2);28 statement.setInt(1,money);29 statement.setString(2,b);30 int res2 = statement.executeUpdate();31 if (res2>0){32 System.out.println("加款完成");33 }else {34 throw new Exception("更新失败,加款失败");35 }36
37 connection.commit();38 System.out.println("成功");39
40 } catch (Exception e) {41 try {42 //这里失败会默认回滚 显式定义方便查看43 connection.rollback();44 } catch (SQLException e1) {45 e1.printStackTrace();46 }47 e.printStackTrace();48 } finally {49 jdbcUtils.release(connection,statement,null);50 }51 }52}总结步骤:
- 1.开启事务 connection.setAutoCommit(false);
- 2.执行SQL
- 3.若事务完成则提交事务 connection.commit();
- 4.捕获到异常自动回滚,也可以在catch显式定义 connection.rollback();
9 数据库连接池
正常程序执行流程:数据库连接->执行->释放连接
连接与释放需要耗费大量系统资源
池化技术:(线程池类似)预先创建连接,使用时直接使用连接好的
- 最小连接数:按常用连接数来设置
- 最大连接数:业务承载的上限 超过则等待
- 等待超时:等待时长超过此时长断开请求
开源数据源
- DBCP
- C3P0
- Druid
编写连接池:实现DataSource接口
DBCP
准备jar包:下载DBCP 下载POOL
- commons-dbcp-1.4.jar
- commons-pool-1.6.jar
测试程序:
配置文件dbcpconfig.properties:
xxxxxxxxxx1341#连接设置2#这里驱动是5.1.47的版本3driverClassName=com.mysql.jdbc.Driver4url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false5username=root6password=1234567
8#初始化连接9initialSize=1010
11#最大连接数量12maxActive=5013
14#最大空闲连接15maxIdle=2016
17#最小空闲连接18minIdle=519
20#超时等待时间以毫秒为单位 6000毫秒/1000等于60秒21maxWait=6000022
23
24#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]25#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。26connectionProperties=useUnicode=true;characterEncoding=utf827
28#指定由连接池所创建的连接的自动提交(auto-commit)状态。29defaultAutoCommit=true30
31#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。32#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE33defaultTransactionIsolation=READ_UNCOMMITTED工具类jdbcUtils_DBCP:
x
1public class jdbcUtils_DBCP {2
3 private static DataSource dataSource = null;4
5 static {6 try{7 InputStream in = jdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("Config/dbcpconfig.properties");8 Properties properties = new Properties();9 properties.load(in);10
11 //创建数据源 工厂模式 -> 创建12 dataSource = BasicDataSourceFactory.createDataSource(properties);13
14 }catch (Exception e){15 e.printStackTrace();16 }17 }18
19 //获取连接20 public static Connection getConnection() throws SQLException {21 return dataSource.getConnection();//从数据源获取连接22 }23}测试程序:
x
1public class TestDBCP {2 public static void main(String[] args) {3 Connection connection = null;4 PreparedStatement statement = null;5
6 try {7 connection = jdbcUtils_DBCP.getConnection();8 //在获取statement前传入SQL语句 ?为占位符9 String sqlStr = "INSERT INTO jdbcstudy.users (id, NAME, PASSWORD, email, birthday) VALUES (?,?,?,?,?)";10
11 statement = connection.prepareStatement(sqlStr);12 //手动传参赋值13 statement.setInt(1,4);14 statement.setString(2,"张三");15 statement.setString(3,"123456");16 statement.setString(4,"123123@qq.com");17 statement.setDate(5,new java.sql.Date(new Date().getTime()));18
19 //执行20 int res = statement.executeUpdate();21 if (res>0){22 System.out.println("插入成功");23 }24
25
26 } catch (SQLException e) {27 e.printStackTrace();28 } finally {29 jdbcUtils.release(connection,statement,null);30 }31 }32}C3P0
准备jar包:下载C3P0
- c3p0-0.9.5.5.jar
- mchange-commons-java-0.2.19.jar
测试程序:
配置文件c3p0-config.xml
xxxxxxxxxx1341 2
3<c3p0-config>4 5 <default-config>6 <property name="driverClass">com.mysql.jdbc.Driverproperty>7 <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=falseproperty>8 <property name="user">rootproperty>9 <property name="password">123456property>10
11
12 <property name="checkoutTimeout">30000property>13 <property name="initialPoolSize">10property>14 <property name="acquireIncrement">5property>15 <property name="maxPoolSize">20property>16 <property name="minPoolSize">5property>17 default-config>18 19 <named-config name="MySQL">20 <property name="driverClass">com.mysql.jdbc.Driverproperty>21 <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=falseproperty>22 <property name="user">rootproperty>23 <property name="password">123456property>24
25 26 <property name="acquireIncrement">5property>27 28 <property name="initialPoolSize">10property>29 30 <property name="maxPoolSize">20property>31 32 <property name="minPoolSize">5property>33 named-config>34c3p0-config>工具类jdbcUtils_C3P0:
x
1public class jdbcUtils_C3P0 {2 private static ComboPooledDataSource dataSource = null;3 static {4 try{5 /*代码配置6 * dataSource = new ComboPooledDataSource();7 * dataSource.setDriverClass();8 * dataSource.setUser();9 * dataSource.setPassword();10 * dataSource.setJdbcUrl();11 *12 * dataSource.setMaxPoolSize();13 * dataSource.setMinPoolSize();*/14
15 //创建数据源 工厂模式 -> 创建16 dataSource = new ComboPooledDataSource("MySQL"); //配置文件写法17
18 }catch (Exception e){19 e.printStackTrace();20 }21 }22
23 //获取连接24 public static Connection getConnection() throws SQLException {25 return dataSource.getConnection();//从数据源获取连接26 }27}测试程序:
xxxxxxxxxx1321public class TestC3P0 {2 public static void main(String[] args) {3 Connection connection = null;4 PreparedStatement statement = null;5
6 try {7 connection = jdbcUtils_C3P0.getConnection();8 //在获取statement前传入SQL语句 ?为占位符9 String sqlStr = "INSERT INTO jdbcstudy.users (id, NAME, PASSWORD, email, birthday) VALUES (?,?,?,?,?)";10
11 statement = connection.prepareStatement(sqlStr);12 //手动传参赋值13 statement.setInt(1,5);14 statement.setString(2,"张四");15 statement.setString(3,"122456");16 statement.setString(4,"123123@qq.com");17 statement.setDate(5,new java.sql.Date(new Date().getTime()));18
19 //执行20 int res = statement.executeUpdate();21 if (res>0){22 System.out.println("插入成功");23 }24 } catch (SQLException e) {25 e.printStackTrace();26 } finally {27 jdbcUtils.release(connection,statement,null);28 }29 }30}