javaweb之jdbc

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: java database connectivity java数据库连接,java语言操作数据库

jdbc概念

java database connectivityjava数据库连接,java语言操作数据库

jdbc本质

是官方定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(jdbc)编程,但真正执行的代码是驱动jar包中的实现类

jdbc快速入门

步骤

  1. 导入驱动jar包(连接什么数据库就导入什么类型的jar包)
  1. 复制mysql-connector-java-5.1.39-bin.jar到项目libs目录下
  2. 右键libs --> Add as Library
  1. 注册驱动(告诉程序使用哪一个数据库的驱动jar包)
  2. 获取数据库连接对象 Connection(java代码与数据库之间的桥梁)
  3. 定义sql语句
  4. 获取执行sql语句的对象 Statement
  5. 执行sql,接收返回结果
  6. 处理结果
  7. 释放资源(先开的后关)

       //1.导入驱动jar包

       //2.注册驱动

       Class.forName("com.mysql.jdbc.Driver");

       //3.获取数据库连接对象

       Connectionconn=DriverManager.getConnection("jdbc:mysql://localhost:3306/contest?useUnicode=true&characterEncoding=UTF-8", "user", "password");

       //4.定义SQL语句

       Stringsql="update hello set age=30 where id=1";

       //5.获取执行SQL的对象Statement

       Statementstmt=conn.createStatement();

       //6.执行SQL

       intresult=stmt.executeUpdate(sql);

       //7.处理结果

       System.out.println(result);

       //8.释放资源

       stmt.close();

       conn.close();

详解各个对象

DriverManager:驱动管理对象

1.注册驱动

static void registerDriver(Driver driver)

我们写代码使用:Class.forName("com.mysql.jdbc.Driver");

查看com.mysql.jdbc.Driver类的源码发现静态代码块(当类被加载进内存,静态代码块会自动执行),本质上还是DriverManager.registerDriver(Driver driver),这样写会提高类的独立性且方便

static {

       try {

           DriverManager.registerDriver(newDriver());

       } catch (SQLExceptionvar1) {

           thrownewRuntimeException("Can't register driver!");

       }

   }

注意:mysql5之后的驱动jar包可以省略注册驱动的步骤

2.获取数据库连接对象

方法:static Connection getConnection(String url, String user, String password)

参数:

  1. url:指定连接的路径语法:jdbc:mysql://ip地址(域名):端口/数据库名例子:jdbc:mysql://localhost:3306/contest注意
  1. 如果连接的是本机的mysql服务器,并且mysql服务端口为3306,则url可以简写为jdbc:mysql:///数据库名
  2. 在url后面设置编码,解决数据库中文乱码 jdbc:mysql:///contest?useUnicode=true&characterEncoding=UTF-8
  1. user:用户名
  2. password:密码

Connection:数据库连接对象

1.获取执行SQL的对象

Statement createStatement()

PreparedStatement prepareStatement(String sql)

2.管理事务

需要先把自动提交修改为手动提交

开启事务:setAutoCommit(boolean autoCommit) 调用该方法设置参数false(关闭自动提交),即开启事务

提交事务:commit()

回滚事务:rollback()

Statement:执行SQL的对象

1.执行SQL
  1. boolean execute(String sql):可以执行任意的SQL
  2. int executeUpdate(String sql):执行DML(insert、update、delete)语句、DDL(create,alter,drop)语句
    返回值:影响的行数。返回值>0则执行成功,反之则执行失败
  3. ResultSet executeQuery(String sql):执行DQL(select)语句
2.insert语句练习

       Connectioncoon=null;

       Statementstmt=null;

       try {

           Class.forName("com.mysql.jdbc.Driver");

           coon=DriverManager.getConnection("jdbc:mysql:///contest?useUnicode=true&characterEncoding=UTF-8", "user", "password");

           Stringsql="insert into hello values(null,'张三',20)";

           stmt=coon.createStatement();

           intresult=stmt.executeUpdate(sql);

           System.out.println(result);

           if (result>0){

               System.out.println("执行成功");

           }else{

               System.out.println("执行失败");

           }

       } catch (ClassNotFoundExceptione) {

           e.printStackTrace();

       } catch (SQLExceptionthrowables) {

           throwables.printStackTrace();

       }finally{

           /*避免空指针异常,因为try语句块中的每一句都有可能异常,那么stmt、coon会为null

           而且无论如何资源都要关闭,将其放在finally中*/

           if(stmt!=null){

               try {

                   stmt.close();

               } catch (SQLExceptionthrowables) {

                   throwables.printStackTrace();

               }

           }

           if (coon!=null){

               try {

                   coon.close();

               } catch (SQLExceptionthrowables) {

                   throwables.printStackTrace();

               }

           }

       }

ResultSet:结果集对象,封装着查询结果

boolean next():游标移动到下一行,并判断当前行是否有数据(最后一行之后),有数据返回true,否则返回false。游标默认在第一行之前

getXxx(参数):获取数据(从一行中获取某个列的数据)

  1. Xxx:代表数据类型如:int getInt(),String getString()
  2. 参数:
  1. int:代表列的编号,从1开始如:getString(1)
  2. String:代表列名称。如:getInt("age")

注意使用步骤:

  1. 游标向下移动一行
  2. 判断是否有数据
  3. 获取数据
select语句练习

数据库的表结构与java类相似

而表中的一行数据代表一个对象

定义一个方法,查询hello表的数据将其封装为对象,然后装载集合,返回。

  1. 定义Hello类
  2. 定义方法 public List<Hello> findAll(){}
  3. SQL语句 select * from hello;

//封装hello表数据的JavaBean

publicclassHello {

   privateintid;

   privateStringname;

   privateintage;

   publicintgetId() {

       returnid;

   }

   publicvoidsetId(intid) {

       this.id=id;

   }

   publicStringgetName() {

       returnname;

   }

   publicvoidsetName(Stringname) {

       this.name=name;

   }

   publicintgetAge() {

       returnage;

   }

   publicvoidsetAge(intage) {

       this.age=age;

   }

   @Override

   publicStringtoString() {

       return"Hello{"+

               "id="+id+

               ", name='"+name+'\''+

               ", age="+age+

               '}';

   }

}

publicclassJdbc {

   publicstaticvoidmain(String[] args){

       List<Hello>list=newJdbc().findAll();

       System.out.println(list);

       System.out.println(list.size());

   }

   //查询所有Emp对象

   publicList<Hello>findAll(){

       Connectioncoon=null;

       Statementstmt=null;

       ResultSetrs=null;

       List<Hello>list=null;

       try {

           Class.forName("com.mysql.jdbc.Driver");

           coon=DriverManager.getConnection("jdbc:mysql://localhost:3306/contest?useUnicode=true&characterEncoding=UTF-8", "user", "password");

           stmt=coon.createStatement();

           Stringsql="select * from hello";

           rs=stmt.executeQuery(sql);

           list=newArrayList<>();

           //遍历结果集,封装对象,装载集合

           Hellohello=null;

           while(rs.next()){

               intid=rs.getInt("id");

               Stringname=rs.getString("name");

               intage=rs.getInt("age");

               /**

                * 封装对象

                * Hello hello = new Hello();

                * 这里不使用上述代码,因为引用太多,浪费栈内存

                * 不如在外面写 Hello hello=null;

                * 再复用引用

                */

               hello=newHello();

               hello.setId(id);

               hello.setAge(age);

               hello.setName(name);

               list.add(hello);

           }

       } catch (ClassNotFoundExceptione) {

           e.printStackTrace();

       } catch (SQLExceptionthrowables) {

           throwables.printStackTrace();

       }finally{

           if(rs!=null){

               try {

                   rs.close();

               } catch (SQLExceptionthrowables) {

                   throwables.printStackTrace();

               }

           }

           if(stmt!=null){

               try {

                   stmt.close();

               } catch (SQLExceptionthrowables) {

                   throwables.printStackTrace();

               }

           }

           if(coon!=null){

               try {

                   coon.close();

               } catch (SQLExceptionthrowables) {

                   throwables.printStackTrace();

               }

           }

       }

       returnlist;

   }

}

输出:

[Hello{id=1, name='ggbond', age=100}, Hello{id=2, name='??', age=20}, Hello{id=3, name='张三', age=20}]

3

抽取jdbc工具类:JDBCUtils

目的:简化书写

分析:

  1. 抽取注册驱动
  2. 抽取一个方法获取连接对象
    需求:不想传递参数(麻烦),还得保证工具类的通用性
    解决:配置文件(只需要改配置文件,代码不用动)
    jdbc.properties(在src目录下)

url=jdbc:mysql:///contest

user=xxx

password=xxx

driver=com.mysql.jdbc.Driver

  1. 抽取一个方法释放资源
JDBCUtils.java

publicclassJDBCUtils {

   privatestaticStringurl;

   privatestaticStringuser;

   privatestaticStringpassword;

   privatestaticStringdriver;

   /**

    * 文件的读取只需一次

    * static{}静态代码块随着类被加载进内存自动执行,且只执行一次

    */

   static{

       //读取jdbc.properties配置文件,获取值

       try {

           //1.创建properties集合类

           Propertiespro=newProperties();

           //获取src目录下文件的方式--> ClassLoader 类加载器(可以加载字节码文件进内存,并且可以获取src目录下资源的路径)

           ClassLoaderclassLoader=JDBCUtils.class.getClassLoader();

           URLres=classLoader.getResource("jdbc.properties");

           Stringpath=res.getPath();

           //2.加载文件

           pro.load(newFileReader(path));

           //3.获取数据,并赋值

           url=pro.getProperty("url");

           user=pro.getProperty("user");

           password=pro.getProperty("password");

           driver=pro.getProperty("driver");

           //4.注册驱动

           Class.forName(driver);

       } catch (IOException|ClassNotFoundExceptione) {

           e.printStackTrace();

       }

   }

   /**

    * 获取连接

    * 工具类方法为了方便使用一般都为静态方法

    * @return connection连接对象

    */

   publicstaticConnectiongetConnection() throwsSQLException {

       returnDriverManager.getConnection(url, user, password);

   }

   /**

    * 释放资源

    * 释放资源有两种情况

    * 1.执行增删改操作,释放2个对象,statement对象,connection对象

    * 2.执行查询操作,释放3个对象,resultSet对象,statement对象,connection对象

    * 因此利用重载机制来实现

    */

   publicstaticvoidclose(Connectionconn, Statementstmt){

       if(stmt!=null){

           try {

               stmt.close();

           } catch (SQLExceptionthrowables) {

               throwables.printStackTrace();

           }

       }

       if(conn!=null){

           try {

               conn.close();

           } catch (SQLExceptionthrowables) {

               throwables.printStackTrace();

           }

       }

   }

   publicstaticvoidclose(Connectionconn, Statementstmt,ResultSetrs){

       if(rs!=null){

           try {

               rs.close();

           } catch (SQLExceptionthrowables) {

               throwables.printStackTrace();

           }

       }

       if(stmt!=null){

           try {

               stmt.close();

           } catch (SQLExceptionthrowables) {

               throwables.printStackTrace();

           }

       }

       if(conn!=null){

           try {

               conn.close();

           } catch (SQLExceptionthrowables) {

               throwables.printStackTrace();

           }

       }

   }

}

jdbc.java

public class Jdbc {

   public static void main(String[] args){

       List<Hello> list = new Jdbc().findAll();

       System.out.println(list);

       System.out.println(list.size());

   }

   //查询所有Emp对象

   public List<Hello> findAll(){

       Connection coon=null;

       Statement stmt=null;

       ResultSet rs=null;

       List<Hello> list=null;

       try {

           coon = JDBCUtils.getConnection();

           stmt = coon.createStatement();

           String sql="select * from hello";

           rs = stmt.executeQuery(sql);

           list=new ArrayList<>();

           //遍历结果集,封装对象,装载集合

           Hello hello=null;

           while(rs.next()){

               int id = rs.getInt("id");

               String name = rs.getString("name");

               int age = rs.getInt("age");

               /**

                * 封装对象

                * Hello hello = new Hello();

                * 这里不使用上述代码,因为引用太多,浪费栈内存

                * 不如在外面写 Hello hello=null;

                * 再复用引用

                */

               hello=new Hello();

               hello.setId(id);

               hello.setAge(age);

               hello.setName(name);

               list.add(hello);

           }

       } catch (SQLException throwables) {

           throwables.printStackTrace();

       }finally{

           JDBCUtils.close(coon, stmt, rs);

       }

       return list;

   }

}

PreparedStatement:执行SQL的对象

1.sql注入问题

在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题

  1. 输入用户任意,输入密码:a' or 'a'='a
  2. sql:select * from user where username ='sadafs' and password = 'a' or 'a'='a'
2.使用PreparedStatement对象解决sql注入问题
  1. Statement对象执行静态的sql语句
  2. PreparedStatement对象执行预编译(动态)的sql语句
  3. 预编译的sql:参数使用?作为占位符
3.步骤
  1. 导入驱动jar包
  2. 注册驱动
  3. 获取数据库连接对象 Connection
  4. 定义sql语句
    注意:sql的参数使用?作为占位符。如:select * from user where username =? and password = ?
  5. 获取执行sql语句的对象 PreparedStatement    conn.preparedStatement(String sql)
  6. 给?赋值
    方法:setXxx(参数1,参数2)
    Xxx:数据类型
    参数1:?的位置编号。从1开始
    参数2:?的值
  7. 执行sql,接收返回结果。无需传递sql语句
  8. 处理结果
  9. 释放资源

注意:后期都会使用PreparedStatement来完成增删改查的所有操作

  1. 可以防止SQL注入
  2. 效率更高
示例代码

//查询数据库是否有某个用户,工具类JDBCUtils.java

public class Jdbc {

   public static void main(String[] args) {

       //键盘录入,接收name和age

       Scanner sc = new Scanner(System.in);

       System.out.println("请输入name");

       String name = sc.nextLine();

       System.out.println("请输入age");

       String age = sc.nextLine();

       //调用方法

       boolean flag = new Jdbc().find(name, age);

       //判断

       if (flag) {

           //存在

           System.out.println("存在用户");

       } else {

           System.out.println("不存在用户");

       }

   }


   public boolean find(String name, String age) {

       Connection coon = null;

       PreparedStatement pstmt = null;

       ResultSet rs = null;

       try {

           //获取连接

           coon = JDBCUtils.getConnection();

           //定义SQL

           String sql = "select * from hello where name =? and age = ?";

           //获取执行SQL的PreparedStatement对象

           pstmt = coon.prepareStatement(sql);

           //sql在执行前要给?赋值

           pstmt.setString(1, name);

           pstmt.setString(2, age);

           //执行查询,不需要传递SQL

           rs = pstmt.executeQuery();

           //判断

           return rs.next();

       } catch (SQLException throwables) {

           throwables.printStackTrace();

       } finally {

           JDBCUtils.close(coon, pstmt, rs);

       }

       return false;

   }

}

JDBC控制事务

1.事务

一个包含多个SQL语句的业务操作。如果这个业务操作被事务管理,里面的SQL语句要么同时成功,要么同时失败

2.操作

  1. 开启事务
  2. 提交事务
  3. 回滚事务

3.使用Connection对象来管理事务

  1. 开启事务:setAutoCommit(boolean autoCommit) 调用该方法设置参数false(关闭自动提交),即开启事务
    在执行SQL之前开启事务
  2. 提交事务:commit()
    当所有SQL都执行完提交事务
  3. 回滚事务:rollback()
    在catch中回滚事务(一旦有异常就会回滚)
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
21天前
|
Java 关系型数据库 数据库连接
JDBC:Java与数据库的“黄金搭档”,为何它如此重要?
JDBC:Java与数据库的“黄金搭档”,为何它如此重要?
34 8
|
21天前
|
Java 数据库连接 API
JDBC:Java数据库连接的“黑科技”大揭秘
JDBC:Java数据库连接的“黑科技”大揭秘
32 7
|
21天前
|
SQL Java 数据库连接
为何JDBC是Java开发者的“心头好”?原因竟然这么简单!
为何JDBC是Java开发者的“心头好”?原因竟然这么简单!
29 3
|
21天前
|
SQL Java 关系型数据库
探索Java数据库连接的奥秘:JDBC技术全攻略
探索Java数据库连接的奥秘:JDBC技术全攻略
40 8
|
21天前
|
SQL Java 数据库连接
JDBC之旅:从陌生到熟悉的Java数据库连接之路
JDBC之旅:从陌生到熟悉的Java数据库连接之路
20 8
|
21天前
|
SQL Java 数据库连接
Java开发者必知:JDBC连接数据库的“三大法宝”
Java开发者必知:JDBC连接数据库的“三大法宝”
17 7
|
21天前
|
SQL Java 数据库连接
深入剖析JDBC:Java与数据库沟通的“桥梁”与“秘密”
深入剖析JDBC:Java与数据库沟通的“桥梁”与“秘密”
14 0
|
1月前
|
SQL druid Java
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
47 3
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)
|
1月前
|
SQL Java 关系型数据库
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(上)
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
58 3
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(上)
|
1月前
|
前端开发 关系型数据库 MySQL
com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver 的区别
这篇文章讨论了`com.mysql.jdbc.Driver`和`com.mysql.cj.jdbc.Driver`两个MySQL驱动类的区别,指出`com.mysql.jdbc.Driver`适用于MySQL 5的`mysql-connector-java`版本,而`com.mysql.cj.jdbc.Driver`适用于MySQL 6及以上版本的`mysql-connector-java`。文章还提到了在实际使用中如何根据MySQL版本选择合适的驱动类。
com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver 的区别