JDBC

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC相关的知识,希望对你有一定的参考价值。

1、什么是jdbc

java database Connector java与数据库的连接器
一套接口,是java代码与数据库的桥梁

2、重要接口和类

1)java.sql.Connection (连接接口--代表了java代码与数据库服务器之间的连接)
2)java.sql.Statement (语句接口--代表了语句对象,可以用来执行各种sql)
3)java.sql.ResultSet (结果集接口--代表查询结果)
4)DriverManager (驱动管理器) 辅助类 -- 获取Connection连接
5)java.sql.Driver (驱动接口)
6)java.sql.SQLException 检查异常, 需要处理

###3
1) 加载驱动 (在新版的jdbc中可以省略此步骤)只需要执行一次即可
Class.forName("com.mysql.jdbc.Driver");// mysql 5.1
Class.forName("com.mysql.cj.jdbc.Driver"); // mysql 8.8

2) 创建连接,创建Connection对象
// jdbc:mysql: 称为连接协议
// localhost: mysql服务器的ip地址 连接本电脑用 localhost
// 3306: 连接端口号
// test3: 数据库名称
// serverTimezone=GMT%2B8 设置连接时区与数据库服务器一致 (连接8.0 mysql时新增 )

    String url = "jdbc:mysql://localhost:3306/test3?serverTimezone=GMT%2B8&useSSL=false"; // 数据库的连接字符串
    String username="root"; // 数据库用户名
    String password="root"; // 数据库的密码(自己定义的数据库密码)
    以上三个定义可以写在工具类中方便以后的使用

    Connection conn = DriverManager.getConnection(url, username, password);

常见问题:
(1):在连接过程中一旦发生异常:java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed
需要添加allowPublicKeyRetrieval=true参数,此异常一种可能的发生情况是MySQL服务重启后,立刻用jdbc连接时

       (2):不写 serverTimezone=GMT%2B8`参数,否则会出现异常:java.sql.SQLException: The server time zone value ‘?D1ú±ê×?ê±??‘,
            另外`GMT%2B8`也必须加 ,否则会出现连接方和数据库时区不一致问题   

       (3):WARN: Establishing SSL connection without server‘s identity verification is not recommended
              要消除这个警告信息,需要加入参数`useSSL=false   参数之间连接用&

3) 创建Statement 对象
    Statement stmt = conn.createStatement();

4) 执行sql语句(执行增删改或查询)

   stmt.executeUpdate(sql) // 用来执行 insert, update, delete   返回结果是int 类型 表示影响的行数
   stmt.executeQuery(sql)  // 用来执行 select

   stmt.execute(sql)       //都可以执行
        返回值是boolean类型 如果执行了增删改,返回false, 如果执行的是查询,那么返回true,

5)结果集
ResultSet rs = stmt.executeQuery(sql);
rs.next();返回的是boolean值表示是否有下一条记录

 next()方法用来移动到下一行记录 getXXX方法用来获取某列数据
 while (rs.next()) {
    int sid = rs.getInt(1);            //(1) 代表从第几行开始
    String sname = rs.getString(2);
    Date birthday = rs.getDate(3);
    String sex = rs.getString(4);

   }
 情况1: getXXX(int 列下标) 用来获取结果集中某一列的数据,其中XXX为数据类型,如果是字符串使用 getString 如果是整数,使用getInt ... ,列下标从1开始
 情况2: getXXX(int 列名) 用来获取结果集中某一列的数据,其中XXX为数据类型,如果是字符串使用 getString 如果是整数,使用getInt
      如:int deptno = rs.getInt("deptno");
        String dname = rs.getString("dname");
        String loc = rs.getString("loc");

6) 关闭资源 先打开的后关闭
rs.close(); // 关闭ResultSet
stmt.close(); // 关闭Statement对象
conn.close(); // 关闭数据库连接

###4 获取自增列的值 Statement.RETURN_GENERATED_KEYS 代表自增的值

Statement stmt = conn.createStatement();
String sql = "insert into student(sid,sname,birthday,sex) values (null,‘XXX‘,‘1999-1-1‘,‘男‘)";
stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
System.out.println(rs.getInt(1));

###5 sql 注入×××问题

问题: Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Statement stmt = conn.createStatement();
// 拼接字符串的办法生成了sql语句
String sql = "select * from user where username=‘" +username+"‘ and password=‘"+password+"‘";

如果结果为:String password = "‘ or ‘1=1"; 会与之匹配从而登录成功

解决方法: // PreparedStatement 预编译的Statement ,可以避免SQL注入×××漏洞
// 让代码的可读性更好

   Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    // sql语句是预先准备好的, 用?作为值的占位符

    String sql  = "select * from USER where username=? and password=?";
    PreparedStatement stmt = conn.prepareStatement(sql);
    // 给sql语句中的? 赋值
    stmt.setString(1, username); // 将username变量赋值给sql语句中第一个?, ?下标从1开始

    stmt.setString(2, "aaa‘ or ‘1‘=‘1"); // 会将整个值当做一个整体,把or当做了值而不是关键字
    ResultSet rs = stmt.executeQuery();; // 会将sql语句以及通过set方法设置的参数值,一起发送给数据库服务器

例: public static boolean login2(String deptno,String dname) {
Connection conn = null;
PreparedStatement pre = null;
ResultSet rst =null;
try {
conn = DriverManager.getConnection(URL, username, password);
String sql = "select * from emp where deptno=?and ename=?" ;
pre = conn.prepareStatement(sql);
pre.setString(1, deptno);
pre.setString(2, dname);
rst = pre.executeQuery();
if(rst.next()){
return true;
}else{
return false;
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("失败",e); //无返回值抛出异常
}finally {
if(rst!=null){
try {
rst.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (pre!=null){
try {
pre.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

以上是关于JDBC的主要内容,如果未能解决你的问题,请参考以下文章

面试常用的代码片段

mysql jdbc源码分析片段 和 Tomcat's JDBC Pool

JDBC操作数据库之查询数据

如何在片段中填充列表视图?

在 myeclipse中进行连接sql server的测试

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段