jdbc基础1

一、jdbc的基础知识

初步入门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 检查异常, 需要处理

jdbc 实现–由各个数据库厂商提供

MySQL Connector/J版本说明

3、jdbc的开发步骤

  1. 加载驱动
Class.forName("驱动类名");
  1. 创建数据库连接
Connection conn = DriverManager.getConnection(连接字符串, 用户名, 密码);

MySQL连接字符串参考

连接字符串参数说明

一些个人理解:
对于以下例题中的参数,jdbc:mysql://localhost:3306/test3?serverTimezone=GMT%2B8&useSSL=false,3306是数据库安装默认端口,如果安装时你修改了就不是这个值。test3是所选用的数据库名称。serverTimezone=GMT%2B8是指你处于东八区,GMT指的是格林威治标准时间,%2B代表+的意思,因为HTML在get请求方式下+可能会被处理为空,为避免出现这种情况所以使用转义字符对其转义。至于useSSL=false就是使用JDBC跟你的数据库连接的时候,你的JDBC版本与MySQL版本不兼容,MySQL的版本更高一些,在连接语句后加上在url中加上“userSSL=true”或“userSSL=false”,就可以连接到更高版本数据库了。
对于“mysql-connector-java 8”以上版本。与老版本有一些区别,
JDBC driver 应由“com.mysql.jdbc.Driver”改为“com.mysql.cj.jdbc.Driver”

  1. 创建Statment(Preparedstatement)对象
Statement stmt = conn.createStatement();

执行增删改

int rows = executeUpdate(sql语句);

执行查询

ResultSet rs = executeQuery(sql语句);
  1. 关闭资源

新增示例代码:

public static void insert() throws Exception{
    // 1. 加载驱动
    Class.forName("com.mysql.cj.jdbc.Driver");
    // 2. 创建数据库连接
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3?serverTimezone=GMT%2B8&useSSL=false", "root" "root");
    // 3. 创建Statment对象,执行sql
    Statement stmt = conn.createStatement();
    // 返回值 int类型 代表影响的记录行数
    String sql = "insert into student(sid,sname,birthday,sex) values (null,'老炮儿','1999-1-1','男')";
    int x = stmt.executeUpdate(sql);
    System.out.println("影响的记录行数  x = " + x);
    // 4. 关闭资源 先打开的后关闭
    stmt.close(); // 关闭statement对象
    conn.close(); // 关闭数据库连接	
}

查询示例代码:

public static void select() throws Exception {
    // 1. 加载驱动
    Class.forName("com.mysql.cj.jdbc.Driver");
    // 2. 创建数据库连接
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3?serverTimezone=GMT%2B8&useSSL=false", "root" "root");
    // 3. 创建Statment对象,执行sql
    Statement stmt = conn.createStatement();
    // executeQuery(sql)  执行sql的方法
    // 返回值ResultSet类型 代表影响的结果集
    String sql = "select sid,sname,birthday,sex from student";
    ResultSet rs = stmt.executeQuery(sql);
    // next()方法用来移动到下一行记录 getXXX方法用来获取某列数据
    while (rs.next()) {
        int sid = rs.getInt(1);
        String sname = rs.getString(2);
        Date birthday = rs.getDate(3);
        String sex = rs.getString(4);
        System.out.println(sid + " " + sname + " " + birthday + " " + sex);
    }
    // 4. 关闭资源 先打开的后关闭
    rs.close(); // 关闭ResultSet
    stmt.close(); // 关闭Statement对象
    conn.close(); // 关闭数据库连接
}

注意
问题1:MySQL Connector/J 8.0.12 驱动连接时需要添加serverTimezone=GMT%2B8参数,否则会出现异常:java.sql.SQLException: The server time zone value ‘Öйú±ê׼ʱ¼ä’,另外GMT%2B8也必须加,否则会出现连接方和数据库时区不一致问题
问题2:在连接过程中一旦发生异常:java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed 需要添加allowPublicKeyRetrieval=true参数,此异常一种可能的发生情况是MySQL服务重启后,立刻用jdbc连接时
问题3:WARN: Establishing SSL connection without server’s identity verification is not recommended 要消除这个警告信息,需要加入参数useSSL=false

4、获取自增列的值

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

5、事务控制

6、注入攻击问题与解决方法

数据库表:

create table xx_user (
   username varchar(20) primary key,
   password varchar(20) not null
);
insert into xx_user values('wang', '123');

登录方法:

// 登录方法,如果有用户名和密码其中之一不正确,返回false表示登录失败
/**
 * 
 * @param username  用户输入的用户名
 * @param password  用户输入的密码
 * @return
 */
public boolean login (String username, String password) {
	Connection conn = null;
	Statement stmt = null;
	ResultSet rs = null;
	try {
		conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:xe", "scott", "tiger");
		stmt = conn.createStatement();
		String sql = "select * from xx_user where username = '"+username+"' and password = '"+password+"'";
		System.out.println(sql);
		rs = stmt.executeQuery(sql);
		if(rs.next()) {
			return true;
		} else {
			return false;
		}
		
	} catch(Exception e) {
		e.printStackTrace();
		throw new RuntimeException("sql执行失败", e);
	} finally {
		if(rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

一个注入攻击问题:

用户名和密码都没有输入正确,但返回true的例子
boolean success = dao.login("laowang", "aaa' or '1'='1");
System.out.println("登录" + success);

解决注入攻击的一种手段:
PrepareStatement对应的sql语句中,可以使用?代表一个未知的值。

  • ?只能代表值,不能是关键字,表名,列名
  • 调用的方法根据?的实际类型而定,例如值是int 调用setInt方法
  • ?的对应的set方法下标从1开始
// 1) 创建 PreparedStatement
PreparedStatement stmt = conn.prepareStatement("select * from xx_user where username = ? and password = ? ");
// 2) 给?占位符赋值
stmt.setString(1, "laowang");
stmt.setString(2, "aaa' or '1'='1"); // 会将整个值当做一个整体,把or当做了值而不是关键字
// 3) 运行sql
ResultSet rs = stmt.executeQuery(); // 会将sql语句以及通过set方法设置的参数值,一起发送给数据库服务器
if(rs.next()) {
	System.out.println("查询到了");
} else {
	System.out.println("没查询到");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值