一、JDBC简介
1、JDBC简介
*Java Database Connectivity : java 连接数据库
*使用java操作数据库需要驱动
-驱动:两个设置之间的桥梁
*如果想要使用java操作数据库,需要数据库生产厂商提供驱动,程序熟悉java代码,熟悉数据库驱动里面的操作代码,程序员不仅要熟悉mysql代码,也要熟悉oracle代码,会造成程序员压力会很大。
*sun公司针对于这个情况,提出解决方案,sun公司和各个生产厂商进行商量,sun公司提供了一套标准的接口,各个数据库厂商实现这个接口,程序员只需要熟悉sun公司提供的这套接口就可以了,这套接口是jdbc。
*想要实际使用jdbc操作数据库,第一步需要操作‘安装’驱动,即导入jar包
二、JDBC入门程序
2、JDBC入门程序
*操作步骤(模板)
-步骤:
(1)加载(注册)数据库驱动
(2)创建与数据库的链接
(3)编写一个sql语句
(4)执行语句(如果执行的是一个查询语句,得到数据的结果)
(5)释放资源
(关闭资源的顺序,谁先打开谁最后关闭,谁最后打开谁先关闭)
-代码演示
public class TestJDBC {
public static void main(String[] args) {
try {
//一、加载数据库驱动,使用类DriverManager
DriverManager.registerDriver(new Driver());
Class.forName("包类路径");
//二、创建与数据库的链接,使用到DriverManager方法getConnection方法创建链接
/* url:数据库的路径 ip+3306
username: 数据库用户名
password:数据库密码*/
Connection conn = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/info","root","123");
//三、编写sql语句
String sql = "select * from dept";
//四、执行sql语句(如果执行的是一个查询语句,得到数据的结果)
/*使用statement执行sql
statement如何得到,Connection里面的方法得到 */
Statement stmt =(Statement) conn.createStatement();
//得到ResultSet 结果及 返回查询的表格
ResultSet rs = stmt.executeQuery(sql);
//遍历结果集ResuleSet
while(rs.next()){
//获取表格里面的每一个值、
int id = rs.getInt("did");
String name = rs.getString("dname");
System.out.println("id:"+id+" name:"+name);
}
//五、释放资源
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
======JDBC操作数据库使用到的类或者接口都在java.sql包里面=====
三、JDBC涉及常用类
3、JDBC时使用到的类
(1)====DriverManager、Driver====
*JDBC的DriverManager对象、
*java.sql包下面
*作用:
-注册数据库驱动
--使用registerDriver(Driver driver)方法注册驱动
*这个registerDriver方法存在一个问题:导致驱动注册两次
-因为在Driver类里面有一个静态代码块,静态代码块会在类加载时执行
-在Driver类加载时候执行registerDriver(new Driver())加载一次
-在jdbc代码里面也写了一个DriverManager.registerDriver(new Driver())又加载一次
*在一般开发不使用上述这个方式,而采用反射来完成
class.forName("com.mysql.jdbc.Driver");
-加载时完成注册
*创建于数据库的连接
*Connection getConnection(String url,String user,String password);
-返回Connection对象、
-三个参数
*第一个参数:
要连接的数据库的ip+端口号3306+数据库名称
-jdbc:mysql://localhost:3306/day15
-如果连接的是本地的数据库同时端口号是3306,这个时候简写方式
jdbc:mysql:///day17
*第二个参数:
要连接的数据库用户名
*第三个参数
要连接的数据库密码
DriverManager.getConnection("jdbc:mysql:///day17","root","123");
(2)====Connection====
*Connection conn = DriverManager.getConnection("jdbc:mysql:///day15","root","123");
-方法返回一个Connection对象
*在java.sql.*;包里面
*用于创建执行sql的对象
-Statement stmt = conn.createStatement():创建一个statement对象
-PreparedStatement preparedStatement = conn.preparedStatement(String sql);
--创建一个PreparedStatement对象,预编译对象,防止sql注入
-CallableStatement prepareCall(String sql):创建一个CallableStatement对象,可以执行存储过程
*可以和事务一起使用
-serAutoCommit(boolean autoCommit):设置数据库是否自动提交,默认是自动提交,值是true、
-rollback():回滚事务里面的语句,回到执行之前的效果
-commit():提交事务,让事务里面语句真正的执行
(3)====Statement====
*Statement stmt = conn.ctreateStatement();
*在java.sql.*;包里面
0
*用来执行sql语句
-ResultSet executeQuery(String sql);执行查询语句,返回的是ResultSet结果集
-int executeUpadte(String sql):执行修改,删除,更新语句,返回的是int类型,返回的成功操作的记录数
--比如增加一条记录,返回int值,int值是成功添加的记录的数量
-boolean execute(String sql):执行sql语句,crud语句都可以执行,返回的是boolean类型
--如果查询出的结果是ResultSet,返true、
--不是查询的操作,返回是false、
*用来执行批处理的操作
-有很多sql语句,批量执行很多的sql语句
-addBatch(String sql):把 多个sql语句放到批处理里面
-clearBatch():清楚批处理里面的语句
-int[] executeBatch():执行批处理的语句
(4)====ResultSet====
*ResultSet rs = stmt.execute(String sql);
*在java.sql.*;包里面
*代表查询之后的结果集,类似查询出来的那个表格
*对返回的结果集进行遍历
while(rs.next()){
rs.getInt();
rs.getString();
.....
}
*画图分析结果集的遍历
-执行while循环,使用next方法,之后一行一行向下遍历,在没有使用next方法时候,在第一行之前
-遍历之后只能向下执行,不能向上,遍历的结果不能修改
-
获取具体的某一行数据
--两种方式:
*一、rs.getString("字段名称");
*二、rs.getString("字段查询出来的所在的位置");
rs.getString(1);
getInt() getString.....等方法
*一般使用第一种方式,比较准确
四、滚动结果集
(5)滚动结果集
*创建statement,使用createStatement(int resultSetType, int resultSetConcurrency);
- 结果集类型
* TYPE_FORWARD_ONLY : 结果集只能向下
* TYPE_SCROLL_INSENSITIVE : 结果集可以滚动
* TYPE_SCROLL_SENSITIVE : 结果集可以滚动
- 结果集并发策略
* CONCUR_READ_ONLY : 结果集不可以修改
* CONCUR_UPDATABLE : 结果集可以修改
- 组合方式
* TYPE_FORWARD_ONLY CONCUR_READ_ONLY: 只能向下,不能修改(默认的方式)
* TYPE_SCROLL_INSENSITIVE CONCUR_READ_ONLY : 结果集可滚动,但不可修改.
* TYPE_SCROLL_SENSITIVE CONCUR_UPDATABLE : 结果集可滚动,而且可修改.
* 如果使用滚动结果集,操作的表里面必须要有一个主键 primary key
*代码演示
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC3 {
public static void main(String[] args) {
try {
// 加载sql驱动;
Class.forName("com.mysql.jdbc.Driver");
// 建立连接
Connection connection = DriverManager.getConnection(
"jdbc:mysql:///info", "root", "123");
// 编写sql语句
String sql = "select * from modify";
// 执行语句
// 得到statement对象,设置滚动结果集
Statement stmt = connection
.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(sql);
// 遍历到第一行记录
rs.absolute(2);
// 更改dname值
rs.updateString("dname", "QQQQ");
// 执行修改
rs.updateRow();
// 是rs移动到第一行之前
rs.absolute(1);
// 遍历结果集
while (rs.next()) {
int did = rs.getInt("did");
String dname = rs.getString("dname");
System.out.println("did :" + did + " dname :" + dname);
}
// 关闭资源
rs.close();
stmt.close();
connection.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
4、jdbc释放资源
*谁先打开,谁最后关闭
- 需要时try-catch对异常进行捕获,需要释放资源的语句写到finally里面
-- 因为finally特点就是,无论程序是否出现异常,finally里面的语句肯定会执行
- 标准的写法
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
}
rs = null;//让jvm快速回收
}
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
}
stmt = null;
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
conn = null;
}
五、JDBC批处理操作
5、批处理的操作(了解)
* Statement.addBatch(sql) :把多个sql语句放入到批处理里面
* executeBatch()方法:执行多个sql语句
- 向一张表中插入多条记录
- 代码
//编写sql
String sql1 = "insert into student values(3,'aaa','222')";
String sql2 = "insert into student values(4,'bbb','333')";
String sql3 = "insert into student values(5,'ccc','444')";
//需要使用批处理操作
stmt = conn.createStatement();
//把这些sql放到批处理里面
stmt.addBatch(sql1);
stmt.addBatch(sql2);
stmt.addBatch(sql3);
//执行这些sql语句
stmt.executeBatch();
六、JDBC工具类封装——加载配置文件(***)
6、封装jdbc操作的方法工具类
*读取配置文件(****)
/*第一种方式读取配置文件 类加载器
* try {
// 读取配置文件
Properties pro = new Properties();
// 类加载器
InputStream in = JDBCUtils.class.getClassLoader()
.getResourceAsStream("dp.properties");
// 加载文件
pro.load(in);
drivername = pro.getProperty("driverName");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
}*/
/*第二种方式读取配置文件 类ResourceBundle*/
//getBundle()方法 当配置文件所在src下面直接写文件的名称(***)
//getString()方法 直接获取配置文件中key的值
drivername = ResourceBundle.getBundle("db").getString("driverName");
url = ResourceBundle.getBundle("db").getString("url");
username = ResourceBundle.getBundle("db").getString("username");
password = ResourceBundle.getBundle("db").getString("password");
* 封装了释放资源的方法
- 由于查询时候需要多关闭一个结果集
- 重载了方法实现不同的操作,关闭不同的连接
七、SQL注入问题解决
7、SQL注入的漏洞的防范
* 用户名输入框里面输入这样一句话 zhangsan' or '1=1
select * from student where username='zhangsan' or '1=1 ' and password='123456'
* 使用prepareStatement对象防范sql注入的漏洞
- 把sql语句先编译出来
* 代码
String sql = "select * from student where username=? and password=?";
//创建一个prepareStatement
PreparedStatement pst = conn.prepareStatement(sql); //把sql先编译
//传递参数
pst.setString(1,stu.getUsername());
pst.setString(2, stu.getPassword());
//执行sql
rs = pst.executeQuery();
*** 执行查询方法 executeQuery();
*** 执行增加,删除,更新 executeUpdate();