JDBC基础操作

JDBC基础

JDBC规范

掌握四个核心对象:
1.DriverManager:用于注册驱动
2.Connection:表示与数据库创建的连接
3.Statement:操作数据库sql语句的对象
4.ResultSet:结果集或者一张虚拟表

JDBC的准备工作

JDBC规范(接口)在哪里:
JDK中:java.sql.; javax.sql.;
需要用到数据库厂商提供的驱动

一个简单的JDBC操作数据库的程序

public class Demo01 {
	public static void main(String[] args) throws Exception{
			//实现JDBC操作
			//1.注册驱动
			DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
			//2.创建连接 url = “jdbc:mysql://localhost:3306/qlgydx?useSSL=false&serverTimezone=UTC”
			// 因为我用的是mysql8.0所以url的方式不太一样
			String url = "jdbc:mysql://localhost:3306/test1?useSSL=false&serverTimezone=UTC";
			String user = "root";
			String password = "466057";
			Connection conn = DriverManager.getConnection(url,user,password);
			System.out.println(conn.getClass());
			//3.得到执行sql语句的Statement对象
			Statement stmt = conn.createStatement();
			//4.执行sql语句,并返回结果
			String sql = "select * from user";
			ResultSet rs = stmt.executeQuery(sql);
			//5.处理结果
			while(rs.next()) {
				//通过列的索引获取各个字段的数据
				System.out.print(rs.getObject(1) + " - ");
				System.out.print(rs.getObject(2) + " - ");
				System.out.print(rs.getObject(3) + " - ");
				System.out.print(rs.getObject(4) + " - ");
				System.out.print(rs.getObject(5) + " - ");
				
				System.out.println();	
			}
			//6.关闭资源
			rs.close();
			stmt.close();
			conn.close();
		}
	}

DriverManager

java.sql.DriverManager类:注册驱动和创建连接

注册驱动:
并不建议用DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());注册驱动

去本机上的mysql安装目录中找到Connector J 8.0 其中的mysql-connector-java-8.0.13.jar为驱动
而src.zip为源码,拷贝到java工程中自己创建的lib文件夹中,然后点击随便ctrl点击某个java.mysql
中的类 然后会出现要附加源码的页面,然后点击attach source 选择WorkSpace Location
然后Browse找到lib/src添加

Driver类中 有一段

static {
	try {
		java.sql.DriverManager.registerDriver(new Driver());
	} catch (SQLException E) {
			throw new RuntimeException("Can't register driver!");
	}
}

因此 在new com.mysql.cj.jdbc.Driver()之后 会调用static中的内容加载一次registerDriver()
而外部代码中又执行了一次registerDriver()

解决办法
Class.forName(“com.mysql.cj.jdbc.Driver”);

Connection连接的三种方法

//第一种getConnection(Stirng url,String user,String password)
String url = "jdbc:mysql://localhost:3306/test1?useSSL=false&serverTimezone=UTC";
String user = "root";
String password = "466057";

Connection conn = DriverManager.getConnection(url,user,password);
System.out.println(conn.getClass());

//第二种 直接传url
String url = "jdbc:mysql://localhost:3306/test1?user=root&password=466057"
		+ "&useSSL=false&serverTimezone=UTC";
Connection conn = DriverManager.getConnection(url);
//第三种 getConnection(String url,Properties info)
String url = "jdbc:mysql://localhost:3306/test1?useSSL=false&serverTimezone=UTC";
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "466057");
Connection conn = DriverManager.getConnection(url,info);

/**
 * url:sun公司与数据库厂商之间的一种协议
 * jdbc:mysql://localhost:3306/test1
 * 协议 子协议      ip    端口号  数据库
 * 也可以写成jdbc:mysql://127.0.0.1:3306/test1  本地mysql
 * 如果是本地mysql  也可以简写 写成jdbc:mysql:///test1
 */

Statement接口

操作sql语句,并返回相应结果的对象
接口的实现在数据库驱动中,用于执行静态sql语句并返回它所生成结果的对象
ResultSet executeQuery(String sql)根据查询语句返回结果集,只能执行select语句
int executeUpdate(String sql)根据执行的DML(insert update delete)语句,返回受影响的行数
boolean execute(String sql)此方法可以执行任意的sql语句,返回boolean值,表示是否返回
ResultSet结果集,仅当执行select语句,并且有返回结果时返回true,否则返回false

ResultSet接口

返回一个结果集(客户端存表数据的对象)

封装结果集

提供一个游标,默认游标指向结果集第一行之前
调用一次next(),游标向下移动一行

提供一些get方法

Object getObject(int columnindex) 根据序号取值,索引从1开始
Object getObject(String columName) 根据列名取值

java的数据类型与数据库中的类型的关系
byte          tityint
short         smallint
int           int
long          bigint
float         float
double        double
String        char varchar 
Date         date
接口的方法

//用getObject()获取的全是object类型,转换成其他类型的时候需要强转

boolean next() 将光标从当前位置向下移动一行
int getInt(int colIndex) 以int形式获取ResultSet结果集当前行指定列号值
int getInt(String colLabel) 以int形式获取ResultSet结果集当前行指定列名值
float getFloat(int colIndex) 以float形式获取ResultSet结果集当前行指定列号值
float getFloat(String colLabel) 以float形式获取ResultSet结果集当前行指定列名值
String getString(int colIndex) 以String 形式获取ResultSet结果集当前行指定列号值
String getString(String colLabel) 以String形式获取ResultSet结果集当前行指定列名值
Date getDate(int columnIndex); 返回的是数据库中的数据库中的Date类型 java.sql.Date
Date getDate(String columnName); 而java.sql.Date 是 继承自 java.util.Date 的
void close() 关闭ResultSet 对象

可移动游标的方法

boolean next() 将光标从当前位置向前移一行。
boolean previous() 将光标移动到此 ResultSet 对象的上一行。
boolean absolute(int row) 参数是当前行的索引,从1开始 根据行的索引定位移动的指定索引行。
void afterLast() 将光标移动到末尾,正好位于最后一行之后。
void beforeFirst() 将光标移动到开头,正好位于第一行之前。

资源释放

conn.close();
stmt.close();
rs.close();
这种关闭是错误的而且顺序也是错的,因为 一旦前面的在关闭时,没有关闭成功,抛出了异常则后面的也无法关闭
要将前面的代码放在try catch中 将三句关闭放到finally中

public static void main(String[] args) throws Exception{
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/test1?useSSL=false&serverTimezone=UTC";
			Properties info = new Properties();
			info.setProperty("user", "root");
			info.setProperty("password", "466057");
			conn = DriverManager.getConnection(url,info);
			//3.得到执行sql语句的Statement对象
			stmt = conn.createStatement();
			//4.执行sql语句,并返回结果
			String sql = "select * from user";
			rs = stmt.executeQuery(sql);
			//5.处理结果
			while(rs.next()) {
				System.out.print("id: " + rs.getInt("id") + " " );
				System.out.print("name: "+rs.getString("name") + " ");
				System.out.print("password: "+ rs.getString("password") + " ");
				System.out.print( "email: " + rs.getString("email") + " ");
				System.out.println();
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		finally {
			//6.关闭资源
			if(rs != null) {
				try {
					rs.close();
				}
				catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
			if(stmt != null) {
				try {
					stmt.close();
				}
				catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
			if(conn != null) {
				try {
					conn.close();
				}
				catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
		}
	}
JDBC的CURD(增删改查)操作
JDBC抽取工具类
/**
 * 抽取数据操作
 * 1. 把创建连接封装到一个工具类
 * 2. 关闭资源也封装到一个工具类
 * @author Echo
 *
 */
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class DBUtils {
	private static String url = "jdbc:mysql://localhost:3306/test1?useSSL=false&serverTimezone=UTC";
	private static String user = "root";
	private static String password = "466057";
	private static String driverClass = "com.mysql.cj.jdbc.Driver";
	static {
		//注册驱动
		try {
			Class.forName(driverClass);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 返回一个数据库连接
	 * @return
	 * @throws SQLException 
	 */
	public static Connection getConnection() throws SQLException {
		return DriverManager.getConnection(url, user, password);
	}
	
	
	/**
	 * 关闭资源
	 * @param rs ResultSet
	 * @param pstmt PreparedStatement
	 * @param conn Connection
	 */
	public static void close(ResultSet rs,PreparedStatement pstmt,Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (pstmt != null) {
			try {
				pstmt.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}
JDBC的操作-插入数据
import java.sql.Connection;
import java.sql.PreparedStatement;

import com.echo.util.DBUtils;

public class Demo01 {
	public static void main(String[] args) throws Exception{
		//JDBC的操作-插入数据
		//1.获取连接
		Connection conn = DBUtils.getConnection();
		
		//2.创建Statement
		//?代表占位
		String sql = "insert into user(id,name,password,email,birthday)"
				+ "values(?,?,?,?,?)";
		//PreparedStatement 是 Statement的子类
		PreparedStatement pstmt = conn.prepareStatement(sql);
		//设置参数
		pstmt.setInt(1, 4);	//设置id为4
		pstmt.setString(2, "zhazha");
		pstmt.setString(3, "123456");
		pstmt.setString(4, "maliu@163.com");
		/**
		 * setDate的日期类型时java.sql.Date,不是java.util.Date
		 */
		pstmt.setDate(5, new java.sql.Date(System.currentTimeMillis()));
		//3.执行插入  返回受影响的行数
		int r = pstmt.executeUpdate();
		System.out.println(r);
		
		//4.关闭资源
		DBUtils.close(null, pstmt, conn);
	}
}
		
JDBC的操作-更改数据
import java.sql.Connection;
import java.sql.PreparedStatement;

import com.echo.util.DBUtils;

public class Demo01 {
	public static void main(String[] args) throws Exception{
		//修改张三的邮箱和密码
		//1.获取连接
		Connection conn = DBUtils.getConnection();
		
		//2.创建Statement
		String sql = "update user set password=?,email=? where name = ?";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		pstmt.setString(1, "654321");
		pstmt.setString(2, "zhangsanvip@163.com");
		pstmt.setString(3, "zhangsan");
		//3.执行
		int row = pstmt.executeUpdate();
		System.out.println("受影响的行数: " + row);
		//4.关闭资源
		DBUtils.close(null, pstmt, conn);
	}
}
		
JDBC的操作-查询数据
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.echo.pojo.User;
import com.echo.util.DBUtils;

public class Demo01 {
	public static void main(String[] args) throws Exception{
		//查询数据
		//1.获取链接
		Connection conn = DBUtils.getConnection();
		//2.创建Statement
		Statement stmt = conn.createStatement();
		//3.执行查询
		ResultSet rs = stmt.executeQuery("select * from user");
		
		//4.遍历结果集 将数据封装到模型中
		List<User> list = new ArrayList<User>();
		while(rs.next()) {
			//把一条数据封装到一个user类[数据模型]模型的包名 model/domain/pojo
			User user = new User();
			user.setId(rs.getInt("id"));
			user.setName(rs.getString("name"));
			user.setPassword(rs.getString("password"));
			user.setEmail(rs.getString("email"));
			user.setBirthday(rs.getDate("birthday"));
			list.add(user);
		}
		for(User user:list) {
			System.out.println(user);
		}
		//5.关闭
		DBUtils.close(rs, stmt, conn);
	}
}

import java.util.Date;

public class User {
	private int id;
	private String name;
	private String password;
	private String email;
	private Date birthday;

	public User() {
		super();
	}
	
	public User(int id, String name, String password, String email, Date birthday) {
		super();
		this.id = id;
		this.name = name;
		this.password = password;
		this.email = email;
		this.birthday = birthday;
	}


	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", password=" + password + ", email=" + email + ", birthday="
				+ birthday + "]";
	}
}
SQL注入
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Scanner;

import com.echo.util.DBUtils;

public class Demo01 {
	//sql注入
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		System.out.println("请输入用户名:");
		String name = input.nextLine();
		System.out.println("请输入密码:");
		String password = input.nextLine();

		try {
			conn = DBUtils.getConnection();
			String sql = "select * from user where name='" + name + "' and password='" + password + "'";
			System.out.println("sql:" + sql);
			pstmt = conn.prepareStatement(sql);
			
			rs = pstmt.executeQuery();
			while(rs.next()) {
				//通过列的索引获取各个字段的数据
				System.out.print("用户ID :" + rs.getObject(1) + " ");
				System.out.print("用户姓名 :" + rs.getObject(2) + " ");
				System.out.print("用户密码 :" + rs.getObject(3) + " ");
				System.out.print("用户邮箱 :" + rs.getObject(4) + " ");
				System.out.print("用户生日 :" + rs.getObject(5) + " ");
				
				System.out.println();
			}
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		finally {
			DBUtils.close(rs, pstmt, conn);
		}
	}
	
}
		

运行结果

使用字符串拼接构造sql注入容易产生sql注入现象
请输入用户名:
lisi
请输入密码:
123’ or 1='1
sql:select * from user where name=‘lisi’ and password=‘123’ or 1=‘1’
用户ID :1 用户姓名 :zhangsan 用户密码 :654321 用户邮箱 :zhangsanvip@163.com 用户生日 :1980-12-04
用户ID :2 用户姓名 :lisi 用户密码 :123456 用户邮箱 :lisi@sina.com 用户生日 :1981-12-04
用户ID :3 用户姓名 :wangwu 用户密码 :123456 用户邮箱 :wangwu@sina.com 用户生日 :1979-12-04

1= ‘1’ 结果为true 就相当于跳过了密码没有判断
相当于执行 select * from user where 1 = ‘1’;

解决方法
不拼接,而是使用PreparedStatement 可以避免吗sql注入问题
String sql = “select * from user where name= ? and password= ?”;
stmt = conn.prepareStatement(sql);
stmt.setString(1,name);
stmt.setString(2,password);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值