一,JDBC概述
JDBC (Java DataBase Connectivity)是Java数据库连接技术的简称,提供连接各种常用数据库
的能力。
二,JDBC工作原理
JDBC API
提供者:Sun公司
作用:Java访问数据库的标准规范。提供给程序员调用的接口与类,集成在java.sql和javax.sql
中。
DriverManager(驱动管理者)
提供者:Sun公司
作用:管理各种不同的JDBC驱动,并获取数据库连接。
JDBC驱动
提供者:各大数据库厂商
作用: JDBC是接口,而JDBC驱动才是接口的实现。每个数据库厂商都有自己的驱动,用来连接
自己公司的数据库。
jdbc核心api
Connection接口的常用方法
Statement接口的常用方法
ResultSet接口的常用方法
三,sql注入
注入原理:利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
防止sql注入:
过滤用户输入的数据中是否包含非法字符;
分步校验!先使用用户名来查询用户,如果查找到了,再比较密码;
使用PreparedStatement接口。
PreparedStatement接口是Statement的子接口,你可以使用该接口来替换Statement接口。
四,数据库连接
一,创建工程导入jar包
二,
/**
* 最终版方法一:标准版
*/
//最终版 将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式获取连接
//实现了数据与代码的分离,实现了解耦
//如果需要修改配置文件信息,可以避免从新打包
//读取配置文件中的4个基本信息dbxlianjie.class.getClassLoader().getResourceAsStream获取类的加载器
// InputStream is = jdbxlianjie.class.getClassLoader().getResourceAsStream("jdbc.properties");或
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String ur1 = pros.getProperty("ur1");
String driverClass = pros.getProperty("driverClass");
//加载驱动
Class.forName(driverClass);
//获取连接
Connection conn = DriverManager.getConnection(ur1,user,password);
// System.out.println(conn);
System.out.println("*****************************************************************************");
/**
* 最终版方法二:不标准 --->帮助理解
*/
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//获取连接
Connection conn1 = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool","root","abc123");
// System.out.println(conn1);
通用连接方法
user=root
password=abc123
ur1=jdbc:mysql://localhost:3306/homework
driverClass=com.mysql.jdbc.Driver
/**
* 获取数据库连接
*/
public static Connection getConnection() throws Exception{
//读取配置文件中的4个基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String ur1 = pros.getProperty("ur1");
String driverClass = pros.getProperty("driverClass");
//加载驱动
Class.forName(driverClass);
//获取连接
Connection conn = DriverManager.getConnection(ur1,user,password);
return conn;
}
五,JDBC增删改查操作
/**
* 数据库查询
*/
public ResultSet select(String sql,Object[]objects,Connection connection) {
ResultSet resultSet = null;
try {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
if (objects != null && objects.length > 0) {
for (int i = 0; i < objects.length; i++) {
preparedStatement.setObject(i + 1, objects[i]);
}
}
resultSet = preparedStatement.executeQuery();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return resultSet;
}
//注意------------------------------------------------------>>>>个方法这样用
// public double getBalance(String cardNo) {
// String sql = "SELECT BALANCE FROM ACCOUNT WHERE CARDNO = ?";
// Object[]objects = {cardNo};
// Connection connection = BaseDao.getConnection();
// ResultSet resultSet = select(sql,objects,connection);
// double balance = 0;
// try {
// while (resultSet.next()){
// balance = resultSet.getDouble(1);
// }
// } catch (SQLException throwables) {
// throwables.printStackTrace();
// } finally {
// close(resultSet,connection);
// }
// return balance;
// }
//通用表查询返回多条数据
public static <T> List<T> getForList(Class<T> clazz, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
//获取结果集元数据ResultSetMetaDate
ResultSetMetaData rsmd = rs.getMetaData();
//通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
//创建集合对象 用于储存多条数据
ArrayList<T> list = new ArrayList<>();
while (rs.next()) {
T t = clazz.newInstance();
//处理结果集一行数据中的每一列:给t对象指定的属性赋值的过程
for (int i = 0; i < columnCount; i++) {
//获取列值
Object columValue = rs.getObject(i + 1);
//获取每个列的列名getColumnName
//获取列的别名getColumnLabel
String columnName = rsmd.getColumnLabel(i + 1);
//给cust对象指定columnName属性,赋值为columValue,通过反射
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);//如果那个类权限不够这个方法可以打开
field.set(t, columValue);
}
list.add(t);//把赋完值的t添加到集合中
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
closeResource(conn, ps, rs);
}
return null;
}
//--------------------------------------------------->>>>>>>>>>>>>这个方法这样用
// public List<Provider> getProvider(int num) {
// String sql = "SELECT id,proCode,proName,proContact,proPhoone FROM provider limit ?,4";
// List<Provider> list = getForList(Provider.class,sql,(num-1)*4);
// list.forEach(System.out::println);
// return list;
// }
/**
* 关闭资源
*/
public static void closeResource(Connection conn, Statement ps, ResultSet rs) {
try {
if (ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 增删改方法
* @param sql
* @param args
*/
public void update(String sql,Object ...args){
Connection conn = null;
PreparedStatement ps = null;
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1,args[i]);
}
ps.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeResource(conn,ps);
}
}
/**
* 针对增删改有返回值
* @param sql
* @param obj
* @return
*/
public int executeUpdate(String sql,Object... obj){
this.getConnection();
int result = 0;
try {
preparedStatement = connection.prepareStatement(sql);
if(obj!=null && obj.length > 0){
for (int i = 0;i< obj.length;i++) {
preparedStatement.setObject((i+1),obj[i]);
}
}
result = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(null);
}
return result;
}
六,事务
package shiwu;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class DaseDao {
/**
* 获取数据库连接
* @return conn
*/
public static Connection getConnection() {
//读取配置文件中的4个基本信息
Connection conn = null;
try {
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String ur1 = pros.getProperty("ur1");
String driverClass = pros.getProperty("driverClass");
//加载驱动
Class.forName(driverClass);
//获取连接
conn = DriverManager.getConnection(ur1,user,password);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return conn;
}
/**
* 数据库查询
*/
public ResultSet select(String sql, Object[]objects, Connection connection) {
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
preparedStatement = connection.prepareStatement(sql);
if (objects != null && objects.length > 0) {
for (int i = 0; i < objects.length; i++) {
preparedStatement.setObject(i + 1, objects[i]);
}
}
resultSet = preparedStatement.executeQuery();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
closeResource(null,preparedStatement,null);
return resultSet;
}
//通用表查询返回多条数据
public static <T> List<T> getForList(Class<T> clazz, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
//获取结果集元数据ResultSetMetaDate
ResultSetMetaData rsmd = rs.getMetaData();
//通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
//创建集合对象 用于储存多条数据
ArrayList<T> list = new ArrayList<>();
while (rs.next()) {
T t = clazz.newInstance();
//处理结果集一行数据中的每一列:给t对象指定的属性赋值的过程
for (int i = 0; i < columnCount; i++) {
//获取列值
Object columValue = rs.getObject(i + 1);
//获取每个列的列名getColumnName
//获取列的别名getColumnLabel
String columnName = rsmd.getColumnLabel(i + 1);
//给cust对象指定columnName属性,赋值为columValue,通过反射
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);//如果那个类权限不够这个方法可以打开
field.set(t, columValue);
}
list.add(t);//把赋完值的t添加到集合中
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
closeResource(conn, ps, rs);
}
return null;
}
/** 增删改方法 考虑事务后
* @param sql
* @param args
*/
public int update(Connection connection,String sql,Object ...args){
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1,args[i]);
}
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeResource(null,ps);
}
return 0;
}
/**
* 关闭资源
*/
public void closeResource(Connection conn, Statement ps) {
try {
if (ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 关闭资源
*/
public static void closeResource(Connection conn, Statement ps, ResultSet rs) {
try {
if (ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package shiwu;
import java.sql.Connection;
import java.sql.SQLException;
public class Test {
/**
* 1,公用一个连接最后关连接
* 2,设置不自动提交
* 3,转账成功提交数据
* 4,出现异常回滚数据
* @param args
*/
public static void main(String[] args) {
DaseDao dao = null;
Connection connection = null;
try {
dao = new DaseDao();
connection = dao.getConnection();
//取消事务的自动提交
connection.setAutoCommit(false);
String sql = "update account set balance = balance - 100 where cardno = ?";
dao.update(connection,sql,"6216760320100101813");
//模拟网络异常
//System.out.println(10 / 0);
String sql1 = "update account set balance = balance + 100 where cardno = ?";
dao.update(connection,sql,"6230515013100527591");
System.out.println("转账成功");
//提交数据
connection.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
//出现异常回滚数据
try {
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
//关闭连接之前把自动提交改过来方便后面使用
try {
connection.setAutoCommit(true);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
dao.closeResource(connection,null);
}
}
}
七,分页
/**
* 获取分页后的页数
* @param chouse 区域编号
* @return 返回页数
*/
@Override
public int count(int chouse) {
Connection connection = BaseDao.getConnection();
String sql = "select count(1) from (SELECT id ,districtid,monitorTime, pm1," +
" pm2 ,monitoringStation FROM airindex WHERE districtId = ?) biao";
Object[] Object = {chouse};
ResultSet resultSet = select(sql,Object, connection);
int count = 0;
try {
while (resultSet.next()){
count = resultSet.getInt(1);
}
if (count % 5 == 0){
count = count / 5;
}else {
count = count / 5 + 1;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
closeResource(connection,resultSet);
}
return count;
}
/**
* 分页处理业务逻辑
*/
public void show(){
int num;
int i = 1;//记录页数
System.out.println("请输入查询的区域编号");
int chouse = scan.nextInt();
int n = airindexDaoimpl.count(chouse);
while (true){
System.out.println("请选择页数");
System.out.println("输入其他数字退出");
num = scan.nextInt();
switch (num){
case 1:
num = 1;
i = 1;
break;
case 2:
if (i == 1){
num = 1;
}else {
num = i - 1;
i -= 1;
}
break;
case 3:
if (i == n){
num = n;
}else{
num = i + 1;
i += 1;
}
break;
case 4:
num = n;
i = n;
break;
default:
return;
}
airindexDaoimpl.getProvider(chouse,num);
System.out.println("1,首页 2,上一页 第" + i +"页/共"+ n +"页 3,下一页 4,尾页");
}
}