
Java Database Connectivity(Java语言连接数据库)
JDBC是SUN公司制定的一套接口,具体实现由数据库厂商完成,使用者面向接口编程
解决不同数据库厂商数据库实现原理不同的问题,一套代码可以共用,简化了程序的开发
环境准备官网下载对应的驱动jar包 MySQL :: Download Connector/J
IDEA开发idea配置比较简单,只需要在环境中引入jar包即可
文本编辑器开发如果不使用ide则需要配置环境变量classpath
如果以前配置过,直接在末尾添加jar包路径
如果没有配置过,新建一个CLASSPATH 环境变量输入 .;后添加jar包路径
classpass 是java编译时寻找的路径,.是指在当前路径中寻找,;是环境变量的分隔符,再在后面添加jdbc的jar包后,编译的时候会自动在这个文件中查找相关类。
⚠️ 注意都是英文字符
JDBC编程六步 第一步:注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库) 第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道。) 第三步:获取数据库操作对象(专门执行sql语句的对象) 第四步:执行SQL语句(DQL DML....) 第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。) 第六步:释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)①注册驱动
Driver driver = new com.mysql.jdbc.Driver(); DriverManager.registerDriver(driver); // 通过驱动管理类注册
mysql中关于Driver类的源码
package com.mysql.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
从第10行往下可以看到这里已经静态注册了驱动,所以可以使用类加载的方式
Class.forName("com.mysql.jdbc.Driver"); //由于静态实现注册,反射即可
②获取连接
String url = "jdbc:mysql://localhost:3306/bjpowernode"; String user = "root"; String pass = "root"; Connection conn = DriverManager.getConnection(url,user,pass); // 通过驱动管理类获取connection对象 System.out.println(conn);
com.mysql.jdbc.JDBC4Connection@66d33a 工具类多态
③获取数据库操作对象获取数据库操作对象Statement专门执行sql语句的
Statement stmt = conn.createStatement();④执行sql
executeUpdate(sql)专门执行DML语句(insert delete update)返回值为影响的数目
⑤处理查询结果集只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。
String sql = "select empno,ename,sal from emp";
rs = stmt.executeQuery(sql); // ResultSet
while (rs.next()) { // 指向下一个,如果有true,没有false
String empno = rs.getString(1);// 数字,从1开始
String ename = rs.getString("ename");// 查询到表的表名
String sal = rs.getString(3);
System.out.println(empno + " " + ename + " " + sal);
}
⑥释放资源
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{......}
catch(){
}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();
}
}
}
从配置文件中读取
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
driver= bundle.getString("driver");
url = bundle.getString("url");
user = bundle.getString("user");
pass = bundle.getString("pass");
jdbc.properties
driver = com.mysql.jdbc.Driver url = jdbc:mysql://localhost:3306/bjpowernode user = root pass = root模拟用户登录功能
public class ForLogin {
public static void main(String[] args) {
Map userLoginInfo = initUI();// 初始化界面,返回登录信息
boolean loginSuccess = login(userLoginInfo);// 判断登录信息
if (loginSuccess) {
System.out.println("success");
} else {
System.out.println("failure");
}
}
private static boolean login(Map userLoginInfo) {
boolean loginSuccess = false;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode", "root", "root");
stmt = conn.createStatement();
String sql = "select * from t_user where name = '" + userLoginInfo.get("name") + "' and pass = '"
+ userLoginInfo.get("pass") + "'";
rs = stmt.executeQuery(sql);
if (rs.next()) {
loginSuccess = true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
...// close 代码过长省略
}
return loginSuccess;
}
private static Map initUI() {
Scanner s = new Scanner(System.in);
System.out.println("输入用户名:");
String name = s.nextLine();
System.out.println("输入密码:");
String pass = s.nextLine();
Map userLoginInfo = new HashMap<>();
userLoginInfo.put("name", name);
userLoginInfo.put("pass", pass);
return userLoginInfo;
}
}
SQL注入
使信息存在安全隐患
sql注入原因用户输入的信息中包含了sql语句中的关键字,并且这些关键字参与了sql语句的编译过程,导致sql语句的原意被扭曲进而达到sql注入
解决sql注入只要用户输入的信息不参与编译的过程,问题就解决了
使用PreparedStatement,PreparedStatement 继承了Satatement 属于预编译的数据库操作对象,预先给sql语句框架编译,然后再给sql语句传值
private static boolean login(Map事务userLoginInfo) { boolean loginSuccess = false; Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode", "root", "root"); // sql语句框架,一个问号表示一个占位符,将来接受传入数据 String sql = "select * from t_user where name = ? and pass = ?"; ps = conn.prepareStatement(sql); // 传值,从下标1开始 ps.setString(1,userLoginInfo.get("name")); ps.setString(2,userLoginInfo.get("pass")); rs = ps.executeQuery(); if (rs.next()) { loginSuccess = true; } } catch (Exception e) { e.printStackTrace(); } finally { ...// close } return loginSuccess; }
jdbc事务是默认自动提交的,执行任意一条语句则自动提交一次,要开启事务只需添加 conn.setAutoCommit(false)
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","root");
// 取消自动提交,开启事务
conn.setAutoCommit(false);
String sql = "update t_act set balance = ? where actno = ?";
ps = conn.prepareStatement(sql);
ps.setDouble(1,1000);
ps.setInt(2,111);
ps.executeUpdate();
// String s=null;
// s.toString();
ps.setDouble(1,1000);
ps.setInt(2,222);
ps.executeUpdate();
// 无异常提交
conn.commit();
}catch (Exception e){
// 异常,回滚
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}finally {
...// close
}
}
JDBC封装
public class DBUtil {
// 工具类 私有化
private DBUtil(){}
// 静态代码块
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 得到conn
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","root");
}
// 关闭,释放资源
public static void close(Connection conn, Statement stmt, ResultSet rs){
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();
}
}
}
}
参见