DriverManager可以注册驱动,就是创建接口的实现类对象。
Class.forName可以将Driver类加载进内存,Driver类中存在静态代码块,随着类的加载静态代码块执行,通过 DriverManager.registerDriver的方式注册好驱动。
获取与数据库的链接对象(Connection类)
我们一般通过try...catch异常包围事务代码,把执行的sql放在try中,commit放在语句尾部,一旦出现任何异常就会触发回滚事务,而无法执行commit。
public class jdbc_demo3_Connection{
public static void main(String[] args) throws Exception {
/*
jdbc的快速入门与学习
*/
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql:///bd1?useSSL=false";
String username="root";
String password="xxxxx";
//2、获取连接
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql语句
String sql1="UPDATE account SET money=1500 where id = 1";
String sql2="UPDATE account SET money=1500 where id = 2";
//4、执行sql的对象
Statement stmt=conn.createStatement();
try {
//开启事务
conn.setAutoCommit(false);
//5、执行sql
int count1 = stmt.executeUpdate(sql1);//返回受影响的行数
int i=3/0;//注意这里,第一条sql可以执行,异常后的sql语句不可以执行;但由于开启事务,所以都无法执行
int count2 = stmt.executeUpdate(sql2);//返回受影响的行数
//6、处理结果
System.out.println(count1);
System.out.println(count2);
//提交事务
conn.commit();
} catch (Exception e) {//抓一个大异常,出现任何异常都会产生事务回滚
//回滚事务
conn.rollback();
e.printStackTrace();
}
//7、释放资源
stmt.cancel();
conn.close();
}
}
String sql="drop database bd2";
//4、执行sql的对象
Statement stmt=conn.createStatement();
//5、执行sql
int count = stmt.executeUpdate(sql);//返回受影响的行数
if(count>0){
System.out.println("修改成功");
}else {
System.out.println("修改失败");
}
ResulSet会自动创建一个游标指向数据行的上一行,也就是id,name....行
随后游标会往下移动来判断该行是否为有效行(是否有数据)
感觉和迭代器有点类似,趁机复习一下
ArrayList list=new ArrayList();
Iterator it=list.iterator();
while(it.hasNext){//判断下一个位置是否还有元素,到null返回false
String str=it.next();//获取下一个位置的元素并且移动指针
System.out.println(str);
}
这里面的get方法(),可以传递id值,也就是第几列。
也可以传递每列的名称。
Statement stmt=conn.createStatement();//DQL语句,数据查询
//5、执行sql
ResultSet rs = stmt.executeQuery(sql);//返回受影响的行数
//6、处理结果,遍历rs中所有的数据
//6。1光标向下移动一行,判断接下来是否还有数据
while(rs.next()){
//int id = rs.getInt(1);
//String name = rs.getString(2);
//String money = rs.getString(3);
//也可以使用名称的方式直接获取
int id = rs.getInt("id");
String name = rs.getString("name");
String money = rs.getString("money");
System.out.println(id);
System.out.println(name);
System.out.println(money);
}
在以后实际网页开发中,我们获取到了所有的数据后,想要使用还需要将数据封装成对应的数据类型,并且存放在集合里面方便操作。
//5、执行sql
ResultSet rs = stmt.executeQuery(sql);//返回受影响的行数
//创建集合
ArrayList list=new ArrayList<>();
//6、处理结果,遍历rs中所有的数据
//6。1光标向下移动一行,判断接下来是否还有数据
while(rs.next()){
account ac=new account();
//也可以使用名称的方式直接获取
int id = rs.getInt("id");
String name = rs.getString("name");
String money = rs.getString("money");
ac.setId(id);
ac.setName(name);
ac.setMoney(money);
list.add(ac);
}
System.out.println(list);
如果我们采用字符串拼接的方式进行账户密码的校验,如果对方给出了如''这样的符号,可能会使我们定义的语句语意发生变化,从而达到破解的效果,这种入侵方式我们称为sql注入。
package com.tangshaojie.jdbc;
import java.sql.*;
public class jdbc_demo6_PreparedStatement {
public static void main(String[] args) throws Exception {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://127.0.0.1:3306/bd1";
String username="root";
String password="XXXX";
//2、获取连接
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql语句
String sql="select * from account where name=?and money=?";
//4、执行sql的对象
PreparedStatement pps=conn.prepareStatement(sql);
//设置?的数值
String TransName="张三";
String TransMoney="1000";
pps.setString(1,TransName);
pps.setString(2,TransMoney);
//5、执行sql
ResultSet rs = pps.executeQuery();
if(rs.next()){
System.out.println("登陆成功");
}else {
System.out.println("登陆失败");
}
//7、释放资源
pps.cancel();
conn.close();
}
}
这种PreparedStatement是如何解决注入问题的呢?
实际上它会在底层自动的添加转义字符'/',这样程序的语句就不会因为注入发生变化。