文章目录
JDBC
1. 简介
-
JDBC(Java Data Base Connectivity, java 数据库连接),由一些接口和类构成的 API。
-
J2SE 的一部分,由 java.sql, javax.sql 包组成。
-
应用程序、JDBC API、数据库驱动及数据库之间的关系。
2. 连接数据的步骤
2.1 注册驱动(只做一次)
-
Class.forName("com.mysql.jdbc.Driver");
推荐使用这种方式,不会对具体的驱动类产生依赖。
-
DriverManager.registerDriber(com.mysql.jdbc.Driver);
会造成 DriverManager 中产生两个一样的驱动,并会对具体的驱动类产生依赖。
-
System.setProperty(“jdbc.driver”, “driver1: driver2”);
虽然不会对具体的驱动类产生依赖;但注册不太方便,所以很少使用。
-
驱动类型(四种类型)
2.2 建立连接(Connection)
- Connection conn = DriverManager.getConnection(url, user, password);
- url 格式:JDBC:子协议:子名称//主机名:端口/数据库名?属性名=属性值&…
- User,password 可以用 “属性名 = 属性值”方式告诉数据库;
- 其他参数如:useUnicode = true&characterEncoding = GBK。
2.3 创建执行 SQL 的语句(Statement)
-
Statement
Statement st = conn.createStatement(); st.executeQuery(sql);
-
PreparedStatement
String sql = "select * from table_name where col_name = ?"; PreparedStatement ps = conn.preparedStatement(sql); ps.setString(1, "col_value"); ps.executeQuery();
2.4 执行语句
2.5 处理执行结果(ResultSet)
ResultSet rs = statement.executeQuery(sql);
While(rs.next()){
rs.getString("col_name");
rs.getInt("col_name");
//...
}
2.6 释放资源
- 释放 ResultSet, Statement, Connection。
- 数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果 Connection 不能及时正确的关闭将导致系统宕机。Connection 的使用原则是尽量晚创建,尽量早的释放。
3. 第一个 JDBC 程序
-
创建测试数据库
CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci; USE jdbcStudy; CREATE TABLE users( id INT(4) PRIMARY KEY, `name` VARCHAR(40), `password` VARCHAR(40), email VARCHAR(60), birthday DATE ); INSERT INTO users(id, `name`, `password`, email, birthday) VALUES(1, '张三', '123456', 'zs@sina.com', '1980-01-02'), (2, '李四', '123456', 'ls@sina.com', '1956-11-02'), (3, '王五', '111111', 'ww@sina.com', '1998-11-22')
-
编写测试代码
import java.sql.*; public class jdbc { public static void main(String[] args) throws ClassNotFoundException, SQLException { // 1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 2. 建立连接 String url = "jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=true"; String userNmae = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url, userNmae, password); // 3. 创建语句 Statement st = conn.createStatement(); // 4. 执行语句 String sql = "SELECT * FROM users"; ResultSet rs = st.executeQuery(sql); // 5. 处理结果 while (rs.next()) { System.out.println("id = " + rs.getObject("id")); System.out.println("name = " + rs.getObject("name")); System.out.println("pwd = " + rs.getObject("password")); System.out.println("email = " + rs.getObject("email")); System.out.println("birth = " + rs.getObject("birthday")); System.out.println("\n"); } // 6. 释放资源 rs.close(); st.close(); conn.close(); } }
-
程序小解:
-
DriverManager:
// DriverManager.registerDriver(new com.mysql.jdbc.Driver()); Class.forName("com.mysql.jdbc.Driver"); //固定写法,加载驱动 Connection conn = DriverManager.getConnection(url, userNmae, password); // conn 代表数据库 // 数据库设置自动提交 // 事务提交 // 事务滚回 conn.rollback(); conn.commit(); conn.setAutoCommit();
-
URL
String url = "jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=true"; // mysql -- 3306 // 协议 ://主机地址:端口号/数据库名?参数1&参数2&参数3 // oralce -- 1521 // jdbc:oracle:thin:@localhost:1521:sid
-
Statement 执行 SQL 的对象;Prepare Statement 执行 SQL 的对象
String sql = "SELECT * FROM users"; // 编写 SQL st.executeQuery(); // 查询操作返回 ResultSet st.execute(); // 执行任何 SQL st.executeUpdate(); // 更新、插入、删除都是用这个,返回一个受影响的行数
-
ResultSet 查询的结果集:封装了所有的查询结果;
-
获得指定的数据类型
rs.getObject(); // 在不知道列类型的情况下使用 // 如果知道列的类型就使用指定的类型 rs.getString(); rs.getInt(); rs.getFloat(); rs.getDate(); ……
-
遍历,指针
rs.beforeFirst(); // 移动到最前面 rs.afterlast(); // 移动到最后面 rs.next(); // 移动到下一个数据 rs.previous(); //移动到前一行 rs.absolute(row); // 移动到指定行
-
-
4. Statement 对象
4.1 基本的 CRUD(创建、读取、更新、删除)
JDBC 中的 statement 对象用于向数据库发送 SQL 语句,想完成对数据库的增删改查,只需要通过这个对象
向数据库发送增删改查语句即可。
-
模板代码
Connection conn = null; Statement st = null; ResultSet rs = null; try{ //获取 Connection //创建 Statement //处理查询结果 ResultSet }finally{ //释放资源ResultSet,Statement,Connection }
-
创建:增加对应 SQL 的 INSERT,返回增加成功的行(记录)数
conn = getConnection(); Statement st = conn.creatStatement(); String sql = "insert into user(name, age, regist_date)" + "values('name',10,now())"; int i = st.executeUpdate(sql); // i 为插入的记录数
-
读取:读取(查询)对应 SQL 的 SELECT,返回查询结果
conn = getConnection(); st = conn.createStatement(); String sql = "select id, name, age,regist_date from user"; rs = st.executeQuery(sql); while (rs.next()) { System.out.print(rs.getInt("id") + " \t\t "); System.out.print(rs.getString("name") + " \t\t "); System.out.print(rs.getInt("age") + " \t\t "); System.out.print(rs.getTimestamp("regist_date") + " \t\t "); System.out.println(); }
-
更新:更新(修改)对应 SQL 的 UPDATE,返回被修改的行(记录)数
conn = getConnection(); Statement st = conn.createStatement(); String sql=“update person set name='new name‘”; int i = st.executeUpdate(sql); //i为符合条件的记录数
-
删除:删除对应 SQL 的 DELETE,返回被删除的行(记录)数
conn = getConnection(); Statement st = conn.createStatement(); String sql=“delete from user where id=1”; int i = st.executeUpdate(sql); //i为删掉的记录数
-
CRUD 总结
- 增、删、改用 Statement.executeUpdate 来完成,返回整数(匹配的记录数),这类操作相对简单。
- 查询用 Statement.executeQuery 来完成,返回的是 ResultSet 对象,ResultSet 中包含了查询的结果;查询相对与增、改要复杂一些,因为有查询结果要处理。
4.2 代码实现
1. 在 src 下建立资源文件db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=true
userNmae=root
password=123456
2. 提取工具类
package com.sd.jdbc.Statement.Utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class jdbcUtils {
private static String driver = null;
private static String url = null;
private static String userName = null;
private static String password = null;
static{
try{
InputStream in = jdbcUtils.class.getClassLoader().getResourceAsStream("db.propertoes");
Properties properties = new Properties();
properties.load(in);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
userName = properties.getProperty("userName");
password = properties.getProperty("password");
// 1. 驱动只用加载一次
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, userName, password);
}
// 释放连接资源
public static void release(Connection conn, Statement st, ResultSet rs){
if(rs != null){
try{
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st != null){
try{
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try{
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3. 增加方法
package com.sd.jdbc.Statement;
import com.sd.jdbc.Statement.Utils.jdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo01 {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = jdbcUtils.getConnection(); //获取数据库连接
st = conn.createStatement(); //获得 SQL 的执行对象
String sql = "INSERT INTO users(id, `name`, `password`, `email`, `birthday`)" +
"VALUES(4, 'SS', '123123', '12341111@sina.com', '2001-09-01')";
int i = st.executeUpdate(sql);
if( i > 0){
System.out.println("插入成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
jdbcUtils.release(conn, st, rs);
}
}
}
4. 删除
package com.sd.jdbc.Statement;
import com.sd.jdbc.Statement.Utils.jdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo02 {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = jdbcUtils.getConnection(); // 获取数据库连接
st = conn.createStatement(); // 获得 SQL 的执行对象
String sql = "DELETE FROM user where id = 3";
int i = st.executeUpdate(sql);
if (i > 0) {
System.out.println("删除成功!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
jdbcUtils.release(conn, st, rs);
}
}
}
5. 修改
package com.sd.jdbc.Statement;
import com.sd.jdbc.Statement.Utils.jdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo03 {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = jdbcUtils.getConnection();
st = conn.createStatement();
String sql = "UPDATE user SET `name`='SS', `emai`=`111@qq.com` WHERE id=2";
int i = st.executeUpdate(sql);
if (i > 0) {
System.out.println("更新成功!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
jdbcUtils.release(conn, st, rs);
}
}
}
6. 查询
package com.sd.jdbc.Statement.Utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo04 {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = jdbcUtils.getConnection();
st = conn.createStatement();
String sql = "select * from user where id=1";
rs = st.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
jdbcUtils.release(conn, st, rs);
}
}
}
4.3 SQL 注入
-
在 SQL 中包含特殊字符或 SQL 的关键字(如:’ or 1 or ')时 Statement 将出现不可预料的结果(出现异常或查询的结果不正确),可用 PreparedStatement 来解决。
-
lPreperedStatement(从 Statement 扩展而来)相对 Statement 的优点:
- 没有 SQL 注入的问题。
- Statement 会使数据库频繁编译 SQL,可能造成数据库缓冲区溢出。
- 数据库和驱动可以对 PreperedStatement 进行优化(只有在相关联的数据库连接没有关闭的情况下有效)。
-
案例:
package com.sd.jdbc.Statement; import com.sd.jdbc.Statement.Utils.jdbcUtils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Demo05 { public static void main(String[] args) { login(" 'or ' 1=1", " 'or ' 1=1"); } public static void login(String userName, String password){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = jdbcUtils.getConnection(); st = conn.createStatement(); String sql = "select * from user where `name`=' "+userName+" ' and ' ' "+password+" ' "; rs = st.executeQuery(sql); while(rs.next()){ System.out.println(rs.getString("name")); System.out.println(rs.getString("password")); System.out.println("=========================="); } } catch (SQLException e) { e.printStackTrace(); }finally { jdbcUtils.release(conn, st, rs); } } }
5. PreparedStatement 对象
PreparedStatement 可防止 SQL 注入。效率更高!
1. 插入
package com.sd.jdbc.PreparedStaement;
import com.sd.jdbc.Statement.Utils.jdbcUtils;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo01 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
try {
conn = jdbcUtils.getConnection();
// 区别: 使用 ? 占位符代替参数
String sql = "insert into user(id, `name`, `password`, `email`, `birthday`) values(?,?,?,?,?)";
st = conn.prepareStatement(sql); // 预编写 SQL,先写 sql,然后不执行
// 手动给参数赋值
st.setInt(1, 4); // id
st.setString(2, "qwer");
st.setString(3, "111111");
st.setString(4, "12312312@qq.com");
st.setDate(5, new java.sql.Date(new Date().getTime()));
// 执行
int i = st.executeUpdate();
if (i > 0) {
System.out.println("插入成功!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
jdbcUtils.release(conn, st, null);
}
}
}
2. 删除
package com.sd.jdbc.PreparedStaement;
import com.sd.jdbc.Statement.Utils.jdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo02 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
try {
conn = jdbcUtils.getConnection();
String sql = "delete from user where id=?";
st = conn.prepareStatement(sql);
//手动给参数赋值
st.setInt(1, 4);
int i = st.executeUpdate();
if (i > 0) {
System.out.println("删除成功!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
jdbcUtils.release(conn, st, null);
}
}
}
3. 更新
package com.sd.jdbc.PreparedStaement;
import com.sd.jdbc.Statement.Utils.jdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo03 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
try {
conn = jdbcUtils.getConnection();
String sql = "update user set `name`=? where id=?";
st = conn.prepareStatement(sql);
st.setString(1, "钱六");
st.setInt(2, 1);
int i = st.executeUpdate();
if (i > 0) {
System.out.println("更新成功!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
jdbcUtils.release(conn, st, null);
}
}
}
4. 查询
package com.sd.jdbc.PreparedStaement;
import com.sd.jdbc.Statement.Utils.jdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Demo04 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = jdbcUtils.getConnection();
String sql = "select * from user where id =?";
st = conn.prepareStatement(sql); //预编译
st.setInt(1, 2); //传递参数
rs = st.executeQuery(); // 执行
if (rs.next()) {
System.out.println(rs.getString("name"));
}
} catch (SQLException e1) {
e1.printStackTrace();
} finally {
jdbcUtils.release(conn, st, rs);
}
}
}
6. 使用 IDEA 连接数据库
- 连接数据库
2. 选择数据库
3. 操作数据库