数据库:JDBC开发

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_1018944104/article/details/83016688

目录

1.什么是JDBC?

2.JDBC运行原理

3.JDBC开发步骤

4.常见API详解

5.实现增删改查

6.登录验证(SQL注入问题)

7.PreparedStatement接口(解决SQL注入问题)

8.DAO开发


1.什么是JDBC?

java database connectivity(java连接数据库技术),是sun公司为了简化开发,设计的一套数据库连接管理规范,主要由一些接口组成。

2.JDBC运行原理

JDBC运行原理如下图所示:

3.JDBC开发步骤

步骤

  1. 注册驱动(通过DriverManager管理驱动)
  2. 建立连接(Connection)
  3. 发送sql命令
  4. 获取响应处理结果
  5. 释放资源

代码

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.mysql.jdbc.Driver;
public class Test {
	public static void main(String[] args) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			//1.注册驱动
			DriverManager.registerDriver(new Driver());
			//2.建立连接
			conn = DriverManager.getConnection(
					//?useSSL=true 加密传输,保证数据安全
					"jdbc:mysql://localhost:3306/mysql?useSSL=true", 
					"root", 
					"root");
			System.out.println(conn);
			//3.发送sql命令
			String sql = "select * from student";
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sql);
			//4.获取响应并处理
			while(rs.next()){//获取记录
				//逐列获取数据
				int sid = rs.getInt("sid");
				String sname = rs.getString("sname");
				int cid = rs.getInt("cid");
				System.out.printf("sid:%s,sname:%s,cid:%s\n",sid,sname,cid);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			//5.释放资源
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (rs != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (rs != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

4.常见API详解

常见类及接口

  • DriverManager:类,驱动管理器
  • Connection:接口,代表与数据库服务的连接
  • Statement:接口,发送sql指令
  • PreparedStatement:Statement接口的接口,发送sql指令(主要用这个)
  • ResultSet:接口,结果集,底层封装指向结果的游标
  • ResultSetMetaData:接口,封装了结果集的元数据信息

DriverManager

作用:注册和管理驱动程序;获取连接对象。

示例:

//注册驱动的两种方式:
//1.通过DriverManager进行注册
DriverManager.registerDriver(new Driver());
//2.加载类的时候静态改代码块里面调用下面的代码进行驱动注册
Class.forName("com.mysql.jdbc.Driver");//(建议使用)
//通过DriverManager获取数据库连接
conn = DriverManager.getConnection(url,user,password);

Connection

作用:作为数据传输通道;用于创建发送sql命令的对象Statement或PreparedStatement。

常用方法:

//设置自动提交
conn.setAutoCommit();
conn.commit();
conn.rollback();
//创建发送sql命令的对象
conn.createStatement();
conn.prepareStatement(sql);//PreparedStatement接口是Statement 接口的子接口
conn.prepareCall(sql);//CallableStatement接口是Statement 接口的子接口 用于调用存储过程
//元数据:解释数据的数据
DatabaseMetaData md = conn.getMetaData();
String dpn = md.getDatabaseProductName();
String driverName = md.getDriverName();
String url = md.getURL();
String username = md.getUserName();

Statement

作用:发送sql指令

子接口:PreparedStatement(用于替换父接口) 和 CallableStatement(调用存储过程)

常用方法:

  • execute:发送任意sql命令,返回值boolean
  • executeQuery:发送查询sql命令,返回值是ResultSet对象
  • executeUpdate:发送增删改和ddl语句,返回值是影响的行数
  • executeBatch:发送批处理命令,返回值int[ ]

ResultSet

作用:底层封装指向结果集的游标,可以获取结果集中的数据

常用方法:

  • next():用于移动游标
  • getX():获取自段值
  • getMetaData():获取结果集的元数据信息
  • ResultSetMetaData rsmd = rs.getMetaData();//获取结果集的元数据信息
  • int columnCount = rsmd.getColumnCount();//获取列数
  • String columnName = rsmd.getColumnName(1);//获取列名

5.实现增删改查(见下面的DAO开发)

6.登录验证

登录验证中的问题?使用Statement对象发送sql指令时,利用检验不合格、不充分绕过验证,从而完成SQL注入。

何为SQL注入

//定义sql字符串
String sql = "select * from user where uname='"+uname+"' and password='"+password+"'";
//若uname和password的值如下:
String username="' or 1=1 or '";
String password="";
//将uname和password传入上面的sql字符串,将得到如下SQL语句
sql = "select * from user where uname='' or 1=1 or '' and password=''";
//这条sql语句的过滤条件是恒成立的,所以,一定会有查询结果,从而无法达到验证登录的效果

SQL注入产生的原因?利用sql的拼接。

如何解决SQL注入问题?使用PreparedStatement接口发送sql指令,即可解决,具体见下文。

7.PreparedStatement接口

什么是PreparedStatement

  • Statement的子接口
  • 采用占位符以及赋值方式解决sql注入问题
  • 采用预编译方式,效率高于Statement,常用PreparedStatement

示例代码

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select * from userinfo where username=? and password=?";
//预编译(语法、语义等检查)
ps = conn.prepareStatement(sql);
//赋值
ps.setString(1, username);
ps.setString(2, password);
rs = ps.executeQuery();
if (rs.next()) {
    System.out.println("登录成功");
} else {
    System.out.println("登录失败");
}

8.DAO开发

什么是DAO?data access object,即数据访问对象,被定义成接口,专门用于对数据库表的进行增删改查操作。

什么是DAO开发?sun公司提出三层开发架构,其中数据持久层是实现与数据库的交互,因此数据持久层开发称为DAO开发。

如何进行DAO开发

dao开发:由接口+实现类组成,每个接口只做一件事,对某一张表进行增删改查操作(松耦合,尽可能避免依赖某一个具体类)

步骤

  1. 创建entity包,并在该包下为数据库中的每一张表创建一个类,数据库表中的每一条记录就对应该类的一个对象称为对象-关系映射;
  2. 创建dao包,并在包下针对数据库的每一张表定义Dao接口以及实现BaseDao类(通用查和通用改的类);
  3. 创建dao.impl包,并在包下创建Dao接口的实现类并继承BaseDao类,然后实现该类;
  4. 测试Dao的增删改查是否正确。
  5. 在开发过程中,会创建获取连接资源和关闭资源的工具类JdbcUtils,并放在util包下。

包、接口与类

完整代码

package entity;

public class User {
	private int uid;
	private String uname;
	private String password;
	public User(){}
	public int getUid() {
		return uid;
	}
	public User setUid(int uid) {
		this.uid = uid;
		return this;
	}
	public String getUname() {
		return uname;
	}
	public User setUname(String uname) {
		this.uname = uname;
		return this;
	}
	public String getPassword() {
		return password;
	}
	public User setPassword(String password) {
		this.password = password;
		return this;
	}
	@Override
	public String toString() {
		return "User [uid=" + uid + ", uname=" + uname + ", password=" + password + "]";
	}
	
}
package dao;

import java.util.List;

import entity.User;

public interface UserDao {
	//增删改查
	int insert(User user);
	int delete(User user);
	int update(User user);
	List<User> select(User user);
	List<User> queryAll();
}
package dao;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.*;

import util.JdbcUtils;

public class BaseDao {
	
	private Connection conn;
	private PreparedStatement ps;
	private ResultSet rs;
	
	//通用增删改方法
	public int excuteUpdate(String sql, Object[] objects){
		int res = 0;
		try {
			//获取数据库连接
			conn = JdbcUtils.getConnection();
			//获取执行sql的对象
			ps = conn.prepareStatement(sql);
			for(int i=0; i<objects.length; i++){
				ps.setObject(i+1, objects[i]);
			}
			res = ps.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeRes(rs, ps, conn);
		}
		return res;
	}
	//通用查询方法
	public <T> List<T> excuteQuery(String sql, Object[] objects, Class<T> clz){
		List<T> res = new ArrayList<>();
		try {
			//获取数据库连接
			conn = JdbcUtils.getConnection();
			//获取执行sql的对象
			ps = conn.prepareStatement(sql);
			for(int i=0; i<objects.length; i++){
				ps.setObject(i+1, objects[i]);
			}
			//执行sql,获取结果集
			rs = ps.executeQuery();
			ResultSetMetaData rmd = rs.getMetaData();
			int columnCount = rmd.getColumnCount();
			while(rs.next()){
				T t = clz.newInstance();
				for(int i=0; i<columnCount; i++){
					Object value = rs.getObject(i+1);
					String columnName = rmd.getColumnName(i+1);
					Field field = clz.getDeclaredField(columnName);
					field.setAccessible(true);
					field.set(t, value);
				}
				res.add(t);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeRes(rs, ps, conn);
		}
		return res;
	}
}

package dao.impl;

import java.util.List;
import dao.*;
import entity.User;

public class UserDaoImpl extends BaseDao implements UserDao {
	@Override
	public int insert(User user) {
		String sql = "insert into user(uname,password) values(?,?)";
		Object[] objects = {user.getUname(),user.getPassword()};
		return excuteUpdate(sql, objects);
	}
	@Override
	public int delete(User user) {
		String sql = "delete from user where uid=?";
		Object[] objects = {user.getUid()};
		return excuteUpdate(sql, objects);
	}
	@Override
	public int update(User user) {
		String sql = "update user set uname=?,password=? where uid=?";
		Object[] objects = {user.getUname(),user.getPassword(),user.getUid()};
		return excuteUpdate(sql, objects);
	}
	@Override
	public List<User> select(User user) {
		String sql = "select * from user where uname=? and password=?";
		Object[] objects = {user.getUname(),user.getPassword()};
		return excuteQuery(sql, objects, User.class);
	}
	@Override
	public List<User> queryAll() {
		String sql = "select * from user";
		Object[] objects = {};
		return excuteQuery(sql, objects, User.class);
	}

}
package util;

import java.io.*;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
	
	private static String driver;
	private static String url;
	private static String user;
	private static String password;
	
	static{
		try {
			InputStream is = 
					JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
			System.out.println(is);
			Properties properties = new Properties();
			properties.load(is);
			is.close();
			//1.注册驱动
			driver = properties.getProperty("driver");
			System.out.println(driver);
			Class.forName(driver);
			url = properties.getProperty("url");
			System.out.println(url);
			user = properties.getProperty("user");
			System.out.println(user);
			password = properties.getProperty("password");
			System.out.println(password);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//获取Connection连接
	public static Connection getConnection() throws SQLException{
		//2.获取数据库连接
		return DriverManager.getConnection(url, user, password);
	}
	//关闭资源
	public static void closeRes(ResultSet rs, PreparedStatement ps, Connection conn){
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (ps != null) {
			try {
				ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
	}
}

jdbc.properties文件的内容,该文件要放置在src下面才能被正常访问。 

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/bd1808?useSSL=true
user=root
password=root

猜你喜欢

转载自blog.csdn.net/qq_1018944104/article/details/83016688