一、JDBC简介
1.1、数据库驱动
这里的驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后才能够使用声卡和网卡,同样道理,我们安装好数据库之后,我们的应用程序也是不能直接使用数据库的,必须要通过相应的数据库驱动程序,通过驱动程序去和数据库打交道。
1.2、JDBC介绍
SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范(接口),称之为JDBC。这套接口由数据库厂商去实现,这样,开发人员只需要学习jdbc接口,并通过jdbc加载具体的驱动,就可以操作数据库。
JDBC全称为:Java Data Base Connectivity(java数据库连接),它主要由接口组成。
组成JDBC的2个包:
java.sql
javax.sql
开发JDBC应用需要以上2个包的支持外,还需要导入相应JDBC的数据库实现(即数据库驱动)。
1.3、DriverManager类讲解
Jdbc程序中的DriverManager用于加载驱动,并创建与数据库的链接,这个API的常用方法:
- DriverManager.registerDriver(new Driver());
- DriverManager.getConnection(url, user, password);
注意:在实际开发中并不推荐采用registerDriver方法注册驱动。原因有二:
1、查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象。
2、程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。
推荐方式:Class.forName(“com.mysql.jdbc.Driver”);
采用此种方式不会导致驱动对象在内存中重复出现,并且采用此种方式,程序仅仅只需要一个字符串,不需要依赖具体的驱动,使程序的灵活性更高。
1.4、数据库URL讲解
URL用于标识数据库的位置,通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为:
常用数据库URL地址的写法:
- Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
- SqlServer写法:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid
- MySql写法:jdbc:mysql://localhost:3306/sid
如果连接的是本地的Mysql数据库,并且连接使用的端口是3306,那么的url地址可以简写为: jdbc:mysql:///数据库
1.5、Connection类讲解
Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,这个对象的常用方法:
- createStatement():创建向数据库发送sql的statement对象。
- prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。
- prepareCall(sql):创建执行存储过程的callableStatement对象。
- setAutoCommit(boolean autoCommit):设置事务是否自动提交。
- commit() :在链接上提交事务。
- rollback() :在此链接上回滚事务。
1.6、Statement类讲解
Jdbc程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法:
- executeQuery(String sql) :用于向数据发送查询语句
- executeUpdate(String sql):用于向数据库发送insert、update或delete语句
- execute(String sql):用于向数据库发送任意sql语句
- addBatch(String sql) :把多条sql语句放到一个批处理中
- executeBatch():向数据库发送一批sql语句执行
1.7、ResultSet类讲解
Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。
ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:
获取任意类型的数据
getObject(int index)
getObject(string columnName)
获取指定类型的数据,例如:
getString(int index)
getString(String columnName)
ResultSet还提供了对结果集进行滚动的方法:
- next():移动到下一行
- Previous():移动到前一行
- absolute(int row):移动到指定行
- beforeFirst():移动resultSet的最前面
- afterLast() :移动到resultSet的最后面
1.8、释放资源
Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象,特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。
二、statement对象介绍
Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
三、使用jdbc对数据库增删改查
package waf.yty.demo2;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.management.RuntimeErrorException;
import org.junit.Test;
public class Demo2 {
@Test
public void fun1() throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://localhost:3306/mydb6";
String username = "root";
String password = "root";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, username, password);
Statement st = conn.createStatement();
// String sql = "INSERT into stu VALUES ('ITCAST_0006','wangWu',26,'female');";
// String sql = "UPDATE stu SET name = 'zhaoLiu',age = 22,gender = 'male' WHERE number = 'ITCAST_0006';";
String sql = "DELETE FROM stu;";
int r = st.executeUpdate(sql);
System.out.println(r);
st.close();
conn.close();
}
@Test
public void fun2() throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://localhost:3306/ytylovefzq3344";
String username = "root";
String password = "root";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, username, password);
Statement st = conn.createStatement();
String sql = "select * from emp;";
ResultSet rs = st.executeQuery(sql);
while (rs.next()) {
int empno = rs.getInt(1);
// int deptno = rs.getInt(6);
String name = rs.getString("ename");
double sal = rs.getDouble("sal");
System.out.println(empno + "," + name + "," + sal);
}
rs.close();
st.close();
conn.close();
}
@Test
public void fun3() throws ClassNotFoundException, SQLException {
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
String driverClassName = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/ytylovefzq3344";
String username = "root";
String password = "root";
Class.forName(driverClassName);
con = DriverManager.getConnection(url, username, password);
stmt = con.createStatement();
String sql = "select * from emp";
rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getObject(1) + "---" + rs.getString("ename") + "---" + rs.getDouble("sal"));
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (con != null) con.close();
}
}
}
四、PreparedStatement对象对数据库进行CRUD操作
PreperedStatement是Statement的子类,它的实例对象可以通过调用Connection.preparedStatement()方法获得,相对于Statement对象而言:PreperedStatement可以避免SQL注入的问题。
Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
PreperedStatement的强大之处:
- 防SQL攻击
- 提高代码的可读性、可维护性
- 提高效率
@Test
public void fun1() throws ClassNotFoundException, SQLException {
String username = "a' or 'a'='a";
String password = "a' or 'a'='a";
boolean result = login(username,password);
System.out.println(result);
}
public boolean login2(String username, String password) throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://localhost:3306/mydb6";
String mySqlUsername = "root";
String mySqlPassword = "root";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, mySqlUsername, mySqlPassword);
String sql = "select * from t_user where username=? and password=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
System.out.println(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
return rs.next();
}
@Test
public void fun2() throws ClassNotFoundException, SQLException {
String username = "zhangSan";
String password = "123";
boolean result = login2(username,password);
System.out.println(result);
}
package waf.yty.demo6;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import org.junit.Test;
import waf.yty.utils.JdbcUtils;
public class JdbcCRUDPreparedStatementTest {
@Test
public void insert() throws SQLException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JdbcUtils.getConnection();
String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)";
stmt = conn.prepareStatement(sql);
//为SQL语句中的参数赋值,注意,索引是从1开始的
stmt.setInt(1, 2);
stmt.setString(2, "死城之谜");
stmt.setString(3, "168");
stmt.setString(4, "603312698@qq.com");
stmt.setDate(5, new java.sql.Date(new Date().getTime()));
int num = stmt.executeUpdate();
if (num > 0) {
System.out.println("数据植入成功!!!");
}
JdbcUtils.release(conn, stmt, rs);
}
@Test
public void update() throws SQLException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JdbcUtils.getConnection();
String sql = "update users set name = ?, password = ? where id = ?";
stmt = conn.prepareStatement(sql);
//为SQL语句中的参数赋值,注意,索引是从1开始的
stmt.setString(1, "核子危机");
stmt.setString(2, "886");
stmt.setInt(3,1);
// stmt.setString(4, "603312698@qq.com");
// stmt.setDate(5, new java.sql.Date(new Date().getTime()));
int num = stmt.executeUpdate();
if (num > 0) {
System.out.println(num);
System.out.println("数据修改成功!!!");
}
JdbcUtils.release(conn, stmt, rs);
}
@Test
public void find() throws SQLException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JdbcUtils.getConnection();
String sql = "select * from users";
stmt = conn.prepareStatement(sql);
//为SQL语句中的参数赋值,注意,索引是从1开始的
// stmt.setString(1, "核子危机");
// stmt.setString(2, "886");
// stmt.setInt(1,2);
// stmt.setString(4, "603312698@qq.com");
// stmt.setDate(5, new java.sql.Date(new Date().getTime()));
rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("name"));
}
JdbcUtils.release(conn, stmt, rs);
}
@Test
public void delete() throws SQLException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JdbcUtils.getConnection();
String sql = "delete from users where name = ?";
stmt = conn.prepareStatement(sql);
//为SQL语句中的参数赋值,注意,索引是从1开始的
stmt.setString(1, "死城之谜");
// stmt.setString(2, "886");
// stmt.setInt(1,2);
// stmt.setString(4, "603312698@qq.com");
// stmt.setDate(5, new java.sql.Date(new Date().getTime()));
int result = stmt.executeUpdate();
if (result > 0) {
System.out.println(result);
System.out.println("删除成功!");
}
JdbcUtils.release(conn, stmt, rs);
}
}