JDBC05-详解各个类2
1、DriverManager:驱动管理对象(类)
功能:
a. 注册驱动:告诉程序该使用哪一个数据库驱动jar包
DriverManager下的方法 public static void registerDriver(java.sql.Driver driver):注册与给定的驱动程序DriverManager
写代码使用:Class.forName("com.mysql.jdbc.Driver"); 把Driver类文件加载进内存,类里的代码会被自动执行。静态代码块的代码会被自动执行。
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块。
static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } }
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。不过建议还是写上。
即Class.forName("com.mysql.jdbc.Driver");可以省略。因为mysql5的jar包中META-INF->services->java.sql.Driver文件下存在“com.mysql.jdbc.Driver”,会自动地注册驱动。如果代码中没有注册会先读取java.sql.Driver文件去自动的注册驱动。
b. 获取数据库连接
-
- 方法:static Connection getConnection(String url, String user, String password) 尝试建立与给定数据库URL的连接。
- 参数:
- url:指定连接的路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
例子:jdbc:mysql://localhost:3306/db3
细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
-
-
- user:用户名
- password:密码
-
2、Connection:数据库连接对象(接口)
java.sql.Connection功能:
a. 获取执行sql的对象
-
- java.sql.Statement createStatement():创建一个Statement对象,用于将SQL语句发送到数据库。
- java.sql.PreparedStatement prepareStatement(String sql):创建一个PreparedStatement对象,用于将参数化的SQL语句发送到数据库。
b. 管理事务
-
- 开启事务:void setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务。将此连接的自动提交模式设置为给定状态。
- 提交事务:void commit()。使自上次提交/回滚以来所做的所有更改都将永久性,并释放此Connection对象当前持有的任何数据库锁。
- 回滚事务:void rollback()。撤销在当前事务中所做的所有更改,并释放此Connection对象当前持有的任何数据库锁。
3、Statement:执行sql的对象(接口)
用于执行静态SQL(里面参数都是给定值)语句并返回其生成的结果的对象。
a. 执行sql
-
- boolean execute(String sql):执行给定的SQL语句,这可能会返回多个结果。可以执行任意的sql,了解即可。
- int executeUpdate(String sql):执行给定的SQL语句,这可能是
INSERT
,UPDATE
,或DELETE
语句,或者不返回任何内容,如SQL DDL语句的SQL语句。执行DML(insert、update、delete)语句、DDL(create、alter、drop)语句。
- 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功,返回值>0的则执行成功,反之则失败。
- ResultSet executeQuery(String sql):执行给定的SQL语句,该语句返回单个
ResultSet
对象。执行DQL(select)语句。
4、练习
1. account表添加一条记录
package cn.itcast.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * account表添加一条记录 insert语句 */ public class JDBCDemo2 { public static void main(String[] args) { Statement stat = null; Connection conn = null; //1. 注册驱动 try { Class.forName("com.mysql.jdbc.Driver"); //2. 定义sql String sql = "insert into account values (null,'wangwu',3000)"; //3. 获取Connection对象 conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //4. 获取执行sql的对象 Statement stat = conn.createStatement(); //5. 执行sql int count = stat.executeUpdate(sql);//count为影响的行数 //6. 处理结果 System.out.println(count); if(count > 0 ){ System.out.println("添加成功!"); }else{ System.out.println("添加失败!"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //7. 释放资源 //避免空指针异常 if(stat != null){ try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
输出结果:
2. account表修改记录
package cn.itcast.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * account表修改记录 */ public class JDBCDemo3 { public static void main(String[] args) { Statement stat = null; Connection conn = null; //1. 注册驱动 try { Class.forName("com.mysql.jdbc.Driver"); //2. 定义sql String sql = "update account set balance = 1500 where id = 3"; //3. 获取Connection对象 conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //4. 获取执行sql的对象 Statement stat = conn.createStatement(); //5. 执行sql int count = stat.executeUpdate(sql);//count为影响的行数 //6. 处理结果 System.out.println(count); if(count > 0 ){ System.out.println("更新成功!"); }else{ System.out.println("更新失败!"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //7. 释放资源 //避免空指针异常 if(stat != null){ try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
输出结果:
3. account表删除一条记录
package cn.itcast.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * account表删除一条记录 */ public class JDBCDemo4 { public static void main(String[] args) { Statement stat = null; Connection conn = null; //1. 注册驱动 try { Class.forName("com.mysql.jdbc.Driver"); //2. 定义sql String sql = "delete from account where id = 3"; //3. 获取Connection对象 conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //4. 获取执行sql的对象 Statement stat = conn.createStatement(); //5. 执行sql int count = stat.executeUpdate(sql);//count为影响的行数 //6. 处理结果 System.out.println(count); if(count > 0 ){ System.out.println("删除成功!"); }else{ System.out.println("删除失败!"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //7. 释放资源 //避免空指针异常 if(stat != null){ try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
输出结果:
4. 新增Student表
package cn.itcast.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * 执行DDL语句 */ public class JDBCDemo5 { public static void main(String[] args) { Statement stat = null; Connection conn = null; //1. 注册驱动 try { Class.forName("com.mysql.jdbc.Driver"); //2. 定义sql String sql = "create table student (id int , name varchar(20))"; //3. 获取Connection对象 conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //4. 获取执行sql的对象 Statement stat = conn.createStatement(); //5. 执行sql int count = stat.executeUpdate(sql);//count为影响的行数 //6. 处理结果 System.out.println(count); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //7. 释放资源 //避免空指针异常 if(stat != null){ try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
输出结果:
5、ResultSet:结果集对象,封装查询结果(接口)
- boolean next():将光标从当前位置向下移动一行。
ResultSet
光标最初位于第一行之前; 第一次调用方法next
使第一行成为当前行; 第二个调用使第二行成为当前行,依此类推。当调用next
方法返回false
时,光标位于最后一行之后。 - getXXX(参数):获取数据
- XXX:代表数据类型。如:int getInt(),String getString()
- 参数:
- int:代表列的编号,从1开始。如:getString(1)
- String:代表带名称。如:getDouble("balance")
int getInt(int coulumnIndex)、int getInt(String columnLabel)、String getString(int coulumnIndex)、String getString(String columnLabel)
- 注意:
- 使用步骤:
1. 游标向下移动一行
2. 判断是否有数据
3. 获取数据
package cn.itcast.jdbc; import java.sql.*; public class JDBCDemo7 { public static void main(String[] args) { Statement stat = null; Connection conn = null; ResultSet rs = null; //1. 注册驱动 try { Class.forName("com.mysql.jdbc.Driver"); //2. 定义sql String sql = "select * from account"; //3. 获取Connection对象 conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //4. 获取执行sql的对象 Statement stat = conn.createStatement(); //5. 执行sql rs = stat.executeQuery(sql);//count为影响的行数 //6. 处理结果 //6.1 让游标向下移动一行,循环判断游标是否是最后一行末尾 while(rs.next()){ //6.2 获取数据 int id = rs.getInt(1); String name = rs.getString("name"); double balance = rs.getDouble(3); System.out.println(id + "---" + name + "---" + balance); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //7. 释放资源 //避免空指针异常 if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stat != null){ try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
输出结果:
6、练习
定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。
1. 定义emp类
2. 定义方法 public List<Emp> findAll(){}
3. 实现方法 select * from emp;
package cn.itcast.jdbc; import java.util.Date; /** * 封装Emp表数据的JavaBean */ public class Emp { private int id; private String ename; private int job_id; private int mgr; private Date joindate; private double salary; private double bonus; private int dept_id; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public int getJob_id() { return job_id; } public void setJob_id(int job_id) { this.job_id = job_id; } public int getMgr() { return mgr; } public void setMgr(int mgr) { this.mgr = mgr; } public Date getJoindate() { return joindate; } public void setJoindate(Date joindate) { this.joindate = joindate; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public int getDept_id() { return dept_id; } public void setDept_id(int dept_id) { this.dept_id = dept_id; } @Override public String toString() { return "Emp{" + "id=" + id + ", ename='" + ename + '\'' + ", job_id=" + job_id + ", mgr=" + mgr + ", joindate=" + joindate + ", salary=" + salary + ", bonus=" + bonus + ", dept_id=" + dept_id + '}'; } }
package cn.itcast.jdbc; import java.sql.*; import java.util.ArrayList; import java.util.List; public class JDBCDemo8 { public static void main(String[] args) { List<Emp> list = new JDBCDemo8().findAll(); System.out.println(list); System.out.println(list.size()); } /** * 查询所有emp对象 * @return */ public List<Emp> findAll(){ Connection conn = null; Statement stat = null; ResultSet rs = null; List<Emp> list = null; try { //1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2. 获取连接 conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //3. 定义sql String sql = "select * from emp"; //4. 获取执行sql的对象 Statement stat = conn.createStatement(); //5. 执行sql rs = stat.executeQuery(sql); //6. 遍历结果集,封装对象,装载集合 Emp emp = null; list = new ArrayList<Emp>(); while(rs.next()){ //获取数据 int id = rs.getInt("id"); String ename = rs.getString("ename"); int job_id = rs.getInt("job_id"); int mgr = rs.getInt("mgr"); Date joindate = rs.getDate("joindate");//这是java.sql.Date,是java.util.Date的子类 double salary = rs.getDouble("salary"); double bonus = rs.getDouble("bonus"); int dept_id = rs.getInt("dept_id"); //创建emp对象,并赋值 emp = new Emp(); emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setBonus(bonus); emp.setDept_id(dept_id); //装载集合 list.add(emp); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //7. 释放资源 //避免空指针异常 if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stat != null){ try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; } }
输出结果:
6、PreparedStatement:执行sql的对象,比Statement更强大(接口)
表示预编译(动态)SQL语句的对象。
1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题。
a. 输入用户随便,输入密码:a' or 'a' = 'a
b. sql:select * from user where username = 'sdfweeyr' and password = 'a' or 'a' = 'a',执行此sql会查出来表中所有的数据
2. 解决sql注入问题:使用PreparedStatement对象来解决
3. 预编译的SQL:参数使用?作为占位符,执行sql时给?赋值即可。
4. 使用PreparedStatement步骤:
a. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
b. 注册驱动
c. 获取数据库连接对象 Connection
d. 定义sql
注意:sql的参数使用?作为占位符。select * from user where username = ? and password = ?;
e. 获取执行sql语句的对象PreparedStatement Connection.prepareStatement(String sql);
f. 给?赋值:
PreparedStatement方法:void setXXX(参数1, 参数2) 将指定参数设置为给定的Java int/double/String/boolean等
值。
参数1:?的位置编号从1开始。int parameterIndex
参数2:?的值
g. 执行sql,接受返回结果,不需要传递sql语句
h. 处理结果
i. 释放资源
package cn.itcast.jdbc; import java.sql.*; import java.util.Scanner; /** * 需求: * 1. 通过键盘录入用户名和密码 * 2. 判断用户是否登录成功 */ public class JDBCDemo11 { public static void main(String[] args) { //1. 键盘录入,接收用户名和密码 Scanner sc = new Scanner(System.in); System.out.println("请输入用户名"); String username = sc.nextLine(); System.out.println("请输入密码"); String password = sc.nextLine(); //2. 调用方法 JDBCDemo11 jdbcDemo11 = new JDBCDemo11(); boolean flag = jdbcDemo11.login(username,password); //3. 判断结果,输出不同语句 if(flag){ System.out.println("登录成功!"); }else{ System.out.println("用户名或密码错误!"); } } /** * 登录方法,使用Prepared Statement实现 */ public boolean login(String username,String password){ if(username == null && password == null){ return false; } Connection conn = null; PreparedStatement pstat = null; ResultSet rs = null; //连接数据库判断是否登录成功 //1. 获取连接 try { conn = JDBCUtils.getConnection(); //2. 定义sql String sql = "select * from user where username= ? and password = ?"; System.out.println(sql); //3. 获取执行sql的对象 pstat = conn.prepareStatement(sql); //给?赋值 pstat.setString(1,username); pstat.setString(2,password); //4. 执行查询,不需要传递sql rs = pstat.executeQuery(); //5. 判断 return rs.next();//如果有下一行则返回true } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.close(rs, pstat, conn); } return false; } }
执行结果:
5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作。
a. 可以防止SQL注入
b. 效率更高