JDBC概述
JDBC(Java Data Base Connectivity,java数据库连接)执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范
JDBC原理
JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信
理解:
java与数据库连接的一种类,jdk提供的接口叫JDBC,数据库的厂商提供的实现类叫驱动,驱动就是实现类,JDBC需要6个步骤,有两种不同的增删改查,反之拼串出现异常,用 PreparedSttement预处理方法,减少更多的代码量,将重复的代码封装在一个类里。
JDBC开发步骤
1.注册驱动.:告知JVM使用的是哪一个数据库的驱动
2.获得连接.使用JDBC中的类,完成对MySQL数据库的连接
3获得语句执行平台:通过连接对象获取对SQL语句的执行者对象
4执行sql语句:使用执行者对象,向数据库执行SQL语句,获取到数据库的执行后的结果
5 处理结果.放到容器,ArraList
6.释放资源. 调用一堆close()方法,释放内存
导入驱动jar包
解压L:mysql-connector-java-5.1.37
目录
docs:文档手册
src:放源码
倒数第三:驱动包
1.md lib目录
1:(项目文件夹new-Folder起名 lib),复制jar包,粘贴到lib目录,存放当前项目需要的所有jar包
2:选择jar包,右键build path / Add to Build Path(添加到环境)牛奶瓶
2.API详解:注册驱动
3.获得连接对象:类名:Connection
jdbc:mysql://localhost:3306/mydb
代码:Connection con = DriverManager.getConnection (“jdbc:mysql://localhost(or 127.0.0.1):3306/mydb”,”root”,”root”);
JDBC的url的格式三部分,部分中间使用冒号分隔
第一部分 JDBC 固定的
第二部分 数据库名称,连接mysql数据库,第二部分当然是mysql了
第三部分 locanhost =127.0.0.1,端口 3306 和DATABASE名称 (mysql组成)
Connection conn 接口 ,DriverManager。。是实现类:多态形式 导包 全导sql包
4.获得语句执行平台:Statement
格式:
String sql = "某SQL语句"; 获取Statement语句执行平台:Statement stmt = con.createStatement();
常用方法:
1、int int:executeUpdate(String sql); --执行 insert、update、delete 返回执行 int(返回行数) 增、删、改、查都用它
2、Result executeQuery(String sql);--执行select语句,返回resultset结果集对象,(二维表格)放到ArrayList
3、boolean execute(String sql);执行select 返回true 执行其他 返回false
5、处理结果集:(执行 inset 、update、delete无序处理)
ResultSet 就是一张二维表格,可以调用boolean next() 方法指向某行记录,当第一次调用next()方法时,便指向第一行记录的位置,可以使用ResultSet提供的getXXX(int col)方法(与索引不同,列从1开始)来获取指定列的数据
6、释放资源:close (关闭顺序:先开的后关 ,反之)
package com.oracle.demo01; //数据的增删改,把红色的部分替换 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class Add新增 { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注册驱动 Class.forName("com.mysql.jdbc.Driver");//静态方法 "" 里面放包名加类名 //2.获取链接对象 (报异常:因为用户输入的串可能写错)后面设置下数据格式 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插这句=红娘 String user="root"; String password="123456";
//Connection:接口 Driver:实现类型 多态形式 全导 sql包 Connection conn=DriverManager.getConnection(url,user,password); //System.out.println(conn);//打印conn测试,如果sql服务关了,会报错 //3.获得执行语句平台 Statement Statement sta=conn.createStatement(); //4.执行sql语句 新增:一套语句执行一句sql语句 String sql="insert into sort(sname) values('口红')";//外面双引号 里面必须单引号
String sql="update sort set sname='金箍棒' where sid=4"; //数据的改
String sql="delete from sort where sid=1";//数据的删 int row=sta.executeUpdate(sql);//执行语句 返回值int 是行数 System.out.println(row); //6.释放资源(先开的后关)关的是变量名 sta.close();//sta在conn的后面 conn.close(); } }
看异常:
最顶上:信息,异常类,位置(找认识的位置)
1.com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column
原因:Sting类型没有加单引号
2.Duplicate entry '1' for key 'PRIMARY'
原因,主键值存在或混乱,要先删除数据或者清空表
3.com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'password' in
原因:可能输入的值的类型不对,确定是否插入的元素时对应的值的类型正确
4.Data truncated for column 'Prices' at row 1
原因:数据过长导致被截断,注意对应值的类型与长度限制——一般把长度调高一点就可以
pm
API详解:处理结果集(执行insert、update、delete无需处理)
rs.next();//指向第一行
rs.getInt(1);//获取第一行第一列的数据
package com.oracle.demo01; //查询 Query import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; public class Query { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注册驱动 Class.forName("com.mysql.jdbc.Driver");//静态方法 //2.获取链接对象 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插这句=红娘 String user="root"; String password="123456"; Connection conn=DriverManager.getConnection(url,user,password); //3.获得语句执行平台 Statement sta=conn.createStatement(); //4.执行SQL String sql="select * from sort"; ResultSet rs=sta.executeQuery(sql);//结果集对象装的二维表格 //5.处理结果集:所有查询才有第五步 (括号里一般是第1列、第2列,但是可以写字段名) ArrayList<Sort> arr=new ArrayList<Sort>();//容器要放在 while外面 while(rs.next()){ //System.out.println(rs.getInt(1)+"..."+rs.getString(2));//()里的1 和2可以改为 sid和 sname Sort sort=new Sort(); sort.setSid(rs.getInt("sid")); sort.setSname(rs.getString("sname")); arr.add(sort);//循环一次就放一次 } System.out.println(arr); //6.释放资源 rs.close(); sta.close(); conn.close(); } }
package com.oracle.demo01; public class Sort { //字段对应属性 private int sid; private String sname; //get set toString方法 public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } @Override public String toString() { return "Sort [sid=" + sid + ", sname=" + sname + "]"; } } ------------------------------------------- package com.oracle.demo01; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Demo01 { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注册驱动 Class.forName("com.mysql.jdbc.Driver");//静态方法 //2.获取链接对象 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插这句=红娘 String user="root"; String password="123456"; Connection conn=DriverManager.getConnection(url,user,password); //System.out.println(conn); //3.获得执行语句平台 Statement sta=conn.createStatement(); //4.执行sql String sql="select count(*) from sort"; ResultSet rs=sta.executeQuery(sql); //5.处理结果集 int count=0; while(rs.next()){ count=rs.getInt(1); } System.out.println(count); //6.释放资源(先开的后关) rs.close(); sta.close(); conn.close(); } }
四、注入问题:
假设有登录案例SQL语句如下:
SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;
此时,当用户输入正确的账号与密码后,查询到了信息则让用户登录。但是当用户输入的账号为XXX 密码为:XXX’ OR ‘a’=’a时,则真正执行的代码变为:
SELECT * FROM 用户表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;
查询语句时永远可以查询出结果的。用户就直接登录成功了,这便是SQL注入问题。
使用PreparedStatement来解决对应的问题。
package com.oracle.demo01; //登录功能 sql注入问题 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class Demo05 { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注册驱动 Class.forName("com.mysql.jdbc.Driver");//静态方法 //2.获取链接对象 (导包都导sql的,不选JDBC的;多态!报异常是因为用户输入的串可能写错)后面设置下数据格式 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插这句=红娘 String user="root"; String password="123456"; Connection conn=DriverManager.getConnection(url,user,password); //System.out.println(conn);//打印conn测试,如果sql服务关了,会报错 //System.out.println(conn); //3.获得执行语句平台 Statement sta=conn.createStatement(); //4.执行sql //让用户输入用户名 Scanner sc=new Scanner(System.in); System.out.println("请输入用户名"); String uname=sc.next(); //用户输入密码 System.out.println("请输入密码"); String pwd=sc.next(); String sql="select count(*) from " + "user where uname='"+uname+"' and pwd='"+pwd+"'"; ResultSet rs=sta.executeQuery(sql); //5.处理结果集 int count=0; while(rs.next()){ count=rs.getInt(1); } System.out.println(count); //6.释放资源(先开的后关) rs.close(); sta.close(); conn.close(); } }
预处理对象 PreparedStatement
使用PreparedStatement预处理对象时,建议每条sql语句所有的实际参数,都使用逗号分隔。
String sql = "insert into sort(sid,sname) values(?,?)";;
PreparedStatement预处理对象代码:
PreparedStatement psmt = conn.prepareStatement(sql)
常用方法:
执行SQL语句:
int executeUpdate(); --insert update delete语句.增删改
ResultSet executeQuery(); --select语句.查询
boolean execute(); --执行select返回true 执行其他的语句返回false.
实际参数
void setXxx(int index, Xxx xx) 指定参数设置为xx
值,将此值发送到数据库时,驱动程序将它转换成一个 SQL Xxx类型
值
举例:setString(2, "家用电器") 把SQL语句中第2个位置的占位符? 替换成实际参数 "家用电器"
package com.oracle.demo01; //预处理对象executeQuery方法
通过预处理对象的executeQuery方法,完成记录的select语句的执行。格式:
1. 注册驱动 2. 获取连接 3. 获取预处理对象4. SQL语句占位符设置实际参数5. 执行SQL语句6. 处理结果集(遍历结果集合)7. 释放资源import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class PrepareStatement { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注册驱动 Class.forName("com.mysql.jdbc.Driver");//静态方法 //2.获取链接对象 (导包都导sql的,不选JDBC的;多态!报异常是因为用户输入的串可能写错)后面设置下数据格式 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插这句=红娘 String user="root"; String password="123456"; Connection conn=DriverManager.getConnection(url,user,password); //System.out.println(conn);//打印conn测试,如果sql服务关了,会报错 //System.out.println(conn); //3.获取语句执行平台对象 String sql="select count(*) from user where" + " uname=? and pwd=?"; PreparedStatement pst=conn.prepareStatement(sql); //4.执行sql Scanner sc=new Scanner(System.in); //让用户输入用户名 System.out.println("请输入用户名: "); String uname=sc.next(); //让用户输入密码 System.out.println("请输入密码:"); String pwd=sc.next(); //给sql语句的? 赋值 pst.setString(1,uname); pst.setString(2, pwd); ResultSet rs=pst.executeQuery();//调query的方法 ()里不用写SQL //5.处理结果集 int count=0; while(rs.next()){ count=rs.getInt(1); } System.out.println(count); //6.释放资源(先开的后关) rs.close(); pst.close(); conn.close(); } }
JDBC工具类
“获得数据库连接”,将在以后的增删改查所有功能中都存在,可以封装工具类JDBCUtils。提供获取连接对象方法,达到代码的重复利用
package com.oracle.demo01; //JDBC工具类 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils { //获取连接对象的方法(静态的) public static Connection getConn(){ Connection conn=null; try { //1.注册驱动(静态方法)(包名+类名) Class.forName("com.mysql.jdbc.Driver"); //2.获取连接对象(导包都导sql里面的,不导jdbc里的;多态!报异常是因为用户输入的串可能写错)后面设置下数据格式 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8"; String user="root"; String password="123456"; conn=DriverManager.getConnection(url,user,password); } catch (ClassNotFoundException | SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return conn; } //释放资源 public static void close(Connection conn,Statement sta){ if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //释放资源2 public static void close(Connection conn,Statement sta,ResultSet rs){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
PreparedStatement 新增功能:
package com.oracle.demo01; //PreparedStatement 新增功能 import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Demo08 { public static void main(String[] args) throws SQLException { add(); } //新增分类Sort public static void add() throws SQLException{ //1.获得连接对象 Connection conn=JDBCUtils.getConn(); //测试一下地址 System.out.println(conn); //2.获取语句执行平台 String sql="insert into sort (sname) values(?)"; PreparedStatement pst=conn.prepareStatement(sql); //3.执行sql pst.setString(1, "打火机"); int row=pst.executeUpdate(); System.out.println(row); //4.释放资源 JDBCUtils.close(conn, pst); } }