[关闭]
@File 2019-10-08T09:34:24.000000Z 字数 8334 阅读 143

JDBC

java 理论


JDBC概述

JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口组成。

JDBC制定了统一访问各类关系数据库的标准接口,为各个数据库厂商提供了标准接口的实现。

JDBC技术进行数据库操作主要有四种方式:

JDBC的体系结构

JDBC API支持两层和三层处理模型进行数据库访问,但在一般的JDBC体系结构由两层组成:

定义了一系列的接口和类,集成在java.sql和javax.sql包中。

JDBC API

JDBC API提供了以下接口和类:

JDBC访问数据库的步骤

加载驱动

  1. String DRIVER_CLASS="com.mysql.cj.jdbc.Driver";//jdbc驱动类名称
  2. Class.forName(DRIVER_CLASS);

获取数据库连接对象

  1. //数据库url
  2. String URL="jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&useSSL=false&serverTimezone=CST&rewriteBatchedStatements=true";
  3. String USER_NAME="root";// 用户名
  4. String PASSWORD="123456";//密码
  5. java.sql.Connection conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);

注意:

  • 在加载驱动及获取连接过程中,可能会出现异常,因此需要注意进行异常处理

  • DRIVER_CLASS:

    • com.mysql.jdbc.Driver:mysql8以下使用
    • com.mysql.cj.jdbc.Driver:mysql8使用
  • URL各参数描述:

    • characterEncoding=utf8:设置编码方式
    • useSSL=false:mysql8.0是不需要建立ssl连接的,你需要显示关闭
    • serverTimezone=CST:serverTimezone是设置时区的,你需要设置CST,CST可视为美国、澳大利亚、古巴或中国的标准时间。
    • rewriteBatchedStatements=true:mysql的批量操作需要设置此项为true

获得语句集(Statement)

  1. //通过Connection对象创建
  2. java.sql.Statement sta - conn.createStatement();

执行sql语句返回结果

这里分为二种:查询和更新(新增、修改、删除)

  1. //执行sql查询返回ResultSet对象
  2. String sql = "select * from a_student";
  3. java.sql.ResultSet rs = sta.executeQuery(String sql);
  4. while(rs.next()){
  5. int id = rs.getInt("id");//按列名
  6. //int id = rs.getInt(1);//按索引
  7. String name = rs.getString("name");
  8. //String name = rs.getString(2);
  9. //...
  10. }
  11. //执行sql更新返回受影响的行数
  12. int rows = sta.executeUpdate(String sql);

释放资源

在使用JDBC与数据交互操作数据库中的数据后,应该明确地关闭所有的数据库资源以减少资源的浪费,对依赖于JVM的垃圾收集如下:

  1. //注意:需从里到外的关闭
  2. try{
  3. if(rs!=null) rs.close();
  4. if(sta!=null) sta.close();
  5. if(conn!=null) conn.close();
  6. } catch(Exception e){
  7. e.printStackTrace();
  8. }

PreparedStatement(预编译语句集)

SQL注入

需求:实现登录功能,需要通过传入的登录名和密码查询数据库表中的用户是否存在。

如果使用的是Statement语句来执行sql语句。

  1. String sql="select * from admin where loginname='"+loginName+"' and loginpwd='"+loginPwd+"'";

如果应用中传入:

  1. 》请输入用户名:
  2. test1
  3. 》请输入密码:
  4. abc' or '1'='1
  5. loginName="test1"
  6. loginPwd="abc' or '1'='1"

那么当上面的sql拼接变量值之后的sql语句为

  1. select * from admin where loginname='test1' and loginpwd='abc' or '1'='1'

那么将登录成功。

PreparedStatement

扩展知识点

批量处理sql:executeBatch()

不使用executeBatch(),而使用executeUpdate()
  1. Class.forName("com.mysql.jdbc.Driver");
  2. Connection conn = DriverManager.getConnection(dbUrl, user, password);
  3. PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");
  4. for(int i=0; i<10000; i++){
  5. pstmt.setString(1, "abc"+i);
  6. pstmt.setInt(2, id);
  7. pstmt.executeUpdate();
  8. }

这样,更新10000条数据,就得访问数据库10000次

使用executeBatch()
  1. Class.forName("com.mysql.jdbc.Driver");
  2. Connection conn = DriverManager.getConnection(dbUrl, user, password);
  3. PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");
  4. for(int i=0; i<10000; i++){
  5. pstmt.setString(1, "abc"+i);
  6. pstmt.setInt(2, id);
  7. pstmt.addBatch();//添加到同一个批处理中
  8. }
  9. pstmt.executeBatch();//执行批处理
  1. @Test
  2. public void testPreparedStatementBatch(){
  3. long starttime = System.currentTimeMillis();
  4. ResultSet rs = null;
  5. PreparedStatement sta = null;
  6. String sql = "insert into a_student(stuNo,stuName,sex,age,create_time) values (?,?,?,?,?)";
  7. try {
  8. //1、加载驱动
  9. Class.forName(DRIVER_CLASS);
  10. //2、获得连接对象
  11. Connection conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
  12. //3、创建语句集
  13. sta = conn.prepareStatement(sql);
  14. for(int i=0;i<10008;i++){
  15. sta.setInt(1, 10+i);
  16. sta.setString(2, "aa"+i);
  17. sta.setString(3, i%2==0?"男":"女");
  18. sta.setInt(4, 20+i);
  19. sta.setTimestamp(5, new java.sql.Timestamp(System.currentTimeMillis()));
  20. sta.addBatch();
  21. if(i%1000==0){
  22. sta.executeBatch();
  23. sta.clearBatch();
  24. }
  25. }
  26. sta.executeBatch();
  27. } catch (ClassNotFoundException e) {
  28. e.printStackTrace();
  29. } catch (SQLException e) {
  30. e.printStackTrace();
  31. } finally {
  32. try {
  33. if(rs!=null) rs.close();
  34. if (sta != null) sta.close();
  35. } catch (SQLException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. long endtime = System.currentTimeMillis();
  40. System.out.println("程序花费时间:" + (endtime-starttime)/1000 + "秒!!");
  41. }

使用配置文件访问数据库

配置文件

.properties为文件后缀,以键值(key/value)的格式保存内容

  1. jdbc.mysql.driverClass=com.mysql.cj.jdbc.Driver
  2. jdbc.mysql.url=jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&useSSL=false&serverTimezone=CST&rewriteBatchedStatements=true
  3. jdbc.mysql.username=root
  4. jdbc.mysql.password=123456
键值配置类
  1. package com.demo1;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.util.Properties;
  5. /**
  6. * @author Ivy Li
  7. * @create 2019-05-23
  8. */
  9. public class DbConfig {
  10. private static String dbConfigFile = "db.properties";
  11. private static Properties props=null;
  12. static {
  13. props = new Properties();
  14. InputStream is =null;
  15. try {
  16. is= DbConfig.class.getClassLoader().getResourceAsStream(dbConfigFile);
  17. props.load(is);
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. } finally {
  21. try {
  22. if(is!=null) is.close();
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }
  28. /**
  29. * 根据键获取值
  30. * @param key 键
  31. * @return
  32. */
  33. public static String getValue(String key){
  34. return props.getProperty(key);
  35. }
  36. }
  1. String DRIVER_CLASS=DbConfig.getValue("jdbc.mysql.driverClass");
  2. String URL=DbConfig.getValue("jdbc.mysql.url");
  3. String USER_NAME=DbConfig.getValue("jdbc.mysql.username");
  4. String PASSWORD=DbConfig.getValue("jdbc.mysql.password");

使用事务

事务简介
什么是事务

事务是一组原子操作单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。更简答的说就是:要么全部执行成功,要么撤销不执行

比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!

事务的特性
普通事务
  1. @Test
  2. public void testTransactionUpdate1(){
  3. ResultSet rs = null;
  4. PreparedStatement sta = null;
  5. Connection conn = null;
  6. try {
  7. //1、加载驱动
  8. Class.forName(DRIVER_CLASS);
  9. //2、获得连接对象
  10. conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
  11. conn.setAutoCommit(false); //设置不自动提交事务
  12. //3、创建语句集
  13. String sql1 = "update a_student set age=age+10 where stuNo=1";
  14. sta = conn.prepareStatement(sql1);
  15. sta.executeUpdate();
  16. String sql2 = "update a_student set age=age-10 where stuNo=2";
  17. sta = conn.prepareStatement(sql2);
  18. sta.executeUpdate();
  19. conn.commit();//提交事务
  20. System.out.println("success...");
  21. } catch (ClassNotFoundException e) {
  22. e.printStackTrace();
  23. } catch (SQLException e) {
  24. e.printStackTrace();
  25. } finally {
  26. try {
  27. if(rs!=null) rs.close();
  28. if (sta != null) sta.close();
  29. if (conn != null) conn.close();
  30. } catch (SQLException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. }
设置事务保存点
  1. @Test
  2. public void testTransactionUpdate2(){
  3. Connection conn = null;
  4. ResultSet rs = null;
  5. PreparedStatement sta = null;
  6. Savepoint sp = null;
  7. try {
  8. //1、加载驱动
  9. Class.forName(DRIVER_CLASS);
  10. //2、获得连接对象
  11. conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
  12. conn.setAutoCommit(false); //设置不自动提交事务
  13. //3、创建语句集
  14. String sql1 = "update a_student set age=age+10 where stuNo=1";
  15. sta = conn.prepareStatement(sql1);
  16. sta.executeUpdate();
  17. sp = conn.setSavepoint();//在这里设置事务回滚点
  18. String sql2 = "update a_student set age=age-10 where stuNo=2";
  19. sta = conn.prepareStatement(sql2);
  20. sta.executeUpdate();
  21. int a = 1/0;//报异常
  22. String sql3 = "update a_student set age=age-10 where stuNo=3";
  23. sta = conn.prepareStatement(sql3);
  24. sta.executeUpdate();
  25. conn.commit();//提交事务
  26. System.out.println("success...");
  27. } catch (Exception e) {
  28. try {
  29. conn.rollback(sp);//回滚到该事务点,即该点之前的会正常执行(sql1)
  30. conn.commit();//回滚了要记得提交,如果没有提交sql1将会自动回滚
  31. } catch (Exception e1){
  32. e1.printStackTrace();
  33. }
  34. e.printStackTrace();
  35. } finally {
  36. try {
  37. if(rs!=null) rs.close();
  38. if (sta != null) sta.close();
  39. } catch (SQLException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. }

Dao设计模式

什么是Dao模式

DAO模式是标准的J2EE设计模式之一.开发人员使用这个模式把底层的数据访问操作和上层的业务逻辑分开,此模式的主要作用是封装对数据库的各种操作;

Dao模式的组成部分
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注