1、什么是JDBC?
Java DataBase Connectivity
在java语言中编写sql语句,对mysql数据库中的数据进行CRUD操作。增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)
2、JDBC相关的类库在哪里?
java.sql.*;
3、JDBC本质上是一堆什么呢?
java.sql.*; 这个包下都是JDBC的接口,SUN公司制定的! JDBC是体现“接口作用”的非常经典的例子。 JDBC降低了耦合度,提高了扩展力。 对于java程序员来说,不需要关心数据库是哪个品牌。只要面向JDBC接口编程就行!
JDBC整个程序的结构当中有三波人????
第一波:SUN公司,负责制定JDBC接口。这些接口已经写好了,在java.sql.*;
第二波:java.sql.*下面的所有接口都要有实现类,这些实现类是数据库厂家编写的。
我们连接的是mysql数据库,mysql数据库厂家的实现类在哪里呢?
mysql-connector-java-5.1.23-bin.jar
jar包中很多.class字节码文件,这是mysql数据库厂家写的接口实现!
注意:如果连接的是oracle数据库,你需要从网上下载oracle的jar包。
mysql-connector-java-5.1.23-bin.jar 这个jar包有一个专业的术语,
大家记住就行:mysql的驱动。
如果是oracle的jar,被称为oracle的驱动。
第三波:我们java程序员,面向JDBC接口写代码就行!
4、编程描述JDBC本质
5、JDBC开发之前的准备工作?
mysql的驱动jar包,需要配置到classpath当中吗?
mysql-connector-java-5.1.23-bin.jar里是字节码,是class文件。
Java虚拟机的类加载器会去加载class文件,类加载器怎么能够
找到这些class文件呢?
classpath没有配置的情况下,默认从当前路径下加载class。
classpath如果配置死了,例如:classpath=D:\abc,则表示固定只从d:\abc目录下找class
classpath=.;D:\course\04-JDBC\resources\MySql Connector Java 5.1.23\mysql-connector-java-5.1.23-bin.jar
. 代表什么?当前路径。
以上的classpath什么意思?
类加载器从当前路径下加载class,如果当前路径下没找到,
则去D:\course\04-JDBC\resources\MySql Connector Java 5.1.23\mysql-connector-java-5.1.23-bin.jar
找class文件。
jar包需要解压吗?
不需要解压,java虚拟机的类加载器有这个能力找到class文件。
6、JDBC编程六步
JDBC编程六部概述
注册驱动与获取连接
package jdbc;
import java.sql.Driver;
import java.sql.*;
public class jdbc01 {
public static void main(String[] args) {
Connection conn=null;
Statement stmt=null;
try {
Driver driver = new com.mysql.cj.jdbc.Driver();
DriverManager.registerDriver(driver);
String url = "jdbc:mysql://127.0.0.1:3306/bjpowernode";
String user = "root";
String password = "123456";
conn = DriverManager.getConnection(url, user, password);
System.out.println("数据库连接对象=" + conn);
stmt=conn.createStatement();
String sql="insert into dept(deptno,dname,loc) values(40,'人事部','北京')";
int count=stmt.executeUpdate(sql);
System.out.println(count==1?"保存成功":"保存失败");
} catch (SQLException e) {
e.printStackTrace();
}finally{
try{
if(stmt!=null){
stmt.close();
}
}catch(SQLException e){
e.printStackTrace();
}
try{
if(conn!=null){
conn.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
}
执行sql与释放资源 与 JDBC执行删除和更新
package jdbc;
import java.sql.*;
public class jdbc02 {
public static void main(String[] args) {
Connection conn=null;
Statement stmt=null;
try {
DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode","root","123456");
System.out.println("数据库连接对象=" + conn);
stmt=conn.createStatement();
String sql="delete from dept where deptno=40";
int count=stmt.executeUpdate(sql);
System.out.println(count==1?"删除成功":"删除失败");
} catch (SQLException e) {
e.printStackTrace();
}finally{
if(stmt!=null){
try{
stmt.close();
}catch(SQLException e){
e.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
}
}
注册驱动的第二种方式 类加载的方式注册驱动
package jdbc;
import com.sun.javaws.IconUtil;
import java.sql.*;
public class jdbc03 {
public static void main(String[] args) {
try{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode","root","123456");
System.out.println(conn);
}catch(SQLException e){
e.printStackTrace();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
从属性资源文件中读取连接数据库信息
jdbcc.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/bjpowernode
user=root
password=123456
package jdbc;
import java.sql.*;
import java.util.ResourceBundle;
public class jdbc04 {
public static void main(String[] args) {
ResourceBundle bundle =ResourceBundle.getBundle("jdbcc");
String driver=bundle.getString("key");
String url=bundle.getString("url");
String user=bundle.getString("user");
String password=bundle.getString("password");
Connection conn=null;
Statement stmt=null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url,user,password);
stmt=conn.createStatement();
String sql="update dept set dname='销售部2',loc='天津'where deptno=20";
int count=stmt.executeUpdate(sql);
System.out.println(count==1?"修改成功":"修改失败");
} catch (SQLException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
if(stmt!=null){
try{
stmt.close();
}catch(SQLException e){
e.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
}
}
处理查询结果集
ResultSet rs 存的是执行sql语句后的查询结果 集
package jdbc;
import javax.swing.*;
import java.sql.*;
public class jdbc05 {
public static void main(String[] args) {
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode","root","123456");
stmt=conn.createStatement();
String sql="select empno,ename,sal from emp";
rs=stmt.executeQuery(sql);
while(rs.next()){
int empno=rs.getInt(1);
String ename=rs.getString(2);
double sal=rs.getDouble(3);
System.out.println(empno+","+ename+","+(sal-100));
}
} catch (SQLException e) {
e.printStackTrace();
}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();
}
}
}
}
}
模拟sql注入
package jdbc;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class jdbc06 {
public static void main(String[] args) {
Map<String,String>userLoginInfo=initUI();
boolean ok=checkNameAndPwd(userLoginInfo.get("loginName"),userLoginInfo.get("loginPwd"));
System.out.println(ok?"登陆成功":"登陆失败");
}
private static boolean checkNameAndPwd(String loginName, String loginPwd) {
boolean ok=false;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode", "root", "123456");
stmt = conn.createStatement();
String sql = "select * from t_user where login_name='"+loginName+"'and login_pwd='"+loginPwd+"'";
System.out.println(sql);
rs = stmt.executeQuery(sql);
if(rs.next()){
ok=true;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn!= null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return ok;
}
private static Map<String, String> initUI(){
System.out.println("欢迎使用该系统,请输入用户名和密码进行身份认证");
Scanner s=new Scanner(System.in);
System.out.println("用户名:");
String loginName=s.nextLine();
System.out.println("密码:");
String loginPwd=s.nextLine();
Map<String,String> useLoginInfo=new HashMap<>();
useLoginInfo.put("loginName",loginName);
useLoginInfo.put("loginPwd",loginPwd);
return useLoginInfo;
}
}
解决sql注入问题
package jdbc;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class jdbc07 {
public static void main(String[] args) {
Map<String,String>userLoginInfo=initUI();
boolean ok=checkNameAndPwd(userLoginInfo.get("loginName"),userLoginInfo.get("loginPwd"));
System.out.println(ok?"登陆成功":"登陆失败");
}
private static boolean checkNameAndPwd(String loginName, String loginPwd) {
boolean ok=false;
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode", "root", "123456");
String sql = "select * from t_user where login_name=? and login_pwd=?";
stmt=conn.prepareStatement(sql);
stmt.setString(1,loginName);
stmt.setString(2,loginPwd);
rs = stmt.executeQuery();
if(rs.next()){
ok=true;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn!= null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return ok;
}
private static Map<String, String> initUI(){
System.out.println("欢迎使用该系统,请输入用户名和密码进行身份认证");
Scanner s=new Scanner(System.in);
System.out.println("用户名:");
String loginName=s.nextLine();
System.out.println("密码:");
String loginPwd=s.nextLine();
Map<String,String> useLoginInfo=new HashMap<>();
useLoginInfo.put("loginName",loginName);
useLoginInfo.put("loginPwd",loginPwd);
return useLoginInfo;
}
}
Statement使用场景
//先使用PreparedStatement-
这个程序输入desc或者asc会出错,因为 select ename,sal from emp order by sal ?会被换成select ename,sal from emp order by sal 'desc’而不是select ename,sal from emp order by sal desc ,
PreparedStatement比较适合传值,Statement比较适合进行字符串的拼接。
京东升降序那不让用户输入,就是不给你注入的机会。
package jdbc;
import java.sql.*;
import java.util.Scanner;
public class jdbc08 {
public static void main(String[] args){
Scanner s=new Scanner(System.in);
System.out.print("请输入desc或asc[desc是表示降序,asc表示升序]:");
String orderKey=s.next();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode", "root", "123456");
String sql="select ename,sal from emp order by sal ?";
ps=conn.prepareStatement(sql);
ps.setString(1,orderKey);
rs=ps.executeQuery();
while(rs.next()){
String ename=rs.getString("ename");
String sal=rs.getString("sal");
System.out.println(ename+","+sal);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
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();
}
}
}
}
}
//再使用statement 此时可以执行了
package jdbc;
import java.sql.*;
import java.util.Scanner;
public class jdbc09 {
public static void main(String[] args){
Scanner s=new Scanner(System.in);
System.out.print("请输入desc或asc[desc是表示降序,asc表示升序]:");
String orderKey=s.next();
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode", "root", "123456");
stmt = conn.createStatement();
String sql="select ename,sal from emp order by sal "+orderKey;
rs=stmt.executeQuery(sql);
while(rs.next()){
String ename=rs.getString("ename");
String sal=rs.getString("sal");
System.out.println(ename+","+sal);
}
} catch (Exception e) {
e.printStackTrace();
}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();
}
}
}
}
}
使用PreparedStatement完成增删改
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class jdbc10 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode", "root", "123456");
String sql="delete from dept where deptno = ?";
ps=conn.prepareStatement(sql);
ps.setInt(1,50);
int count=ps.executeUpdate();
System.out.println(count);
} catch (Exception e) {
e.printStackTrace();
}finally {
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
模糊查询
package jdbc;
import java.sql.*;
public class jdbc11 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode", "root", "123456");
String sql="select ename from emp where ename like ?";
ps=conn.prepareStatement(sql);
ps.setString(1, "%O%");
rs=ps.executeQuery();
while (rs.next()){
System.out.println(rs.getString("ename"));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
JDBC事务
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class jdbc12 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode", "root", "123456");
conn.setAutoCommit(false);
String sql=" update t_act set balance =? where actno= ?";
ps=conn.prepareStatement(sql);
ps.setDouble(1,10000);
ps.setString(2,"A");
int count=ps.executeUpdate();
ps.setDouble(1,10000);
ps.setString(2,"B");
count+=ps.executeUpdate();
System.out.println(count==2?"转账成功":"转账失败");
conn.commit();
} catch (Exception e) {
try {
if(conn!=null){
conn.rollback();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
JDBC工具类的封装
外部文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/bjpowernode
user=root
password=123456
封装类
package jdbc.utils;
import java.sql.*;
import java.util.ResourceBundle;
public class DBUtil {
private DBUtil(){};
private static ResourceBundle bundle=ResourceBundle.getBundle("jdbcc");
static{
try {
Class.forName(bundle.getString("driver"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
String url=bundle.getString("url");
String user=bundle.getString("user");
String password=bundle.getString("password");
Connection conn=DriverManager.getConnection(url,user,password);
return conn;
}
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();
}
}
}
}
测试类
package jdbc;
import java.sql.*;
public class jdbc11 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode", "root", "123456");
String sql="select ename from emp where ename like ?";
ps=conn.prepareStatement(sql);
ps.setString(1, "%O%");
rs=ps.executeQuery();
while (rs.next()){
System.out.println(rs.getString("ename"));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
行级锁for update(此知识点为sql语句知识)
关于DQL语句的悲观锁 对于一个DQL语句来说,末尾是可以添加这样一个关键字的:for update
select ename,sal from emp where job=‘MANAGER’ for update ; 以上sql语句的含义是: 在本次事务的执行过程中,job='MANAGER’的记录被查询, 这些记录在我查询的过程中,任何人,任何事务都不能对 这些记录进行修改操作,直到我当前事务结束。
这种机制被称为:行级锁机制(又叫做悲观锁!)
在mysql中是这样的, 当使用select…where…for updare…时,mysql进行row lock(行锁)还是table lock(表锁)只取决于是否能使用索引(例如主键,unique字段),能则为行锁,否则为表锁: 未查到数据则无锁,而使用’<>’,'like’等操作时,索引会失效,自然进行的是table lock。
所以慎用for update。
整个表锁住的时候会导致性能性能降低,谨慎使用。
使用for update的时候,最好是锁主键值,或者具有unique约束的字段, 锁别的字段可能会导致整个表锁住。
|