JDBC入门
1.1 回顾
之前操作mysql数据库:
1)使用mysql客户端工具
2)使用客户端连接mysql服务器
3)发送sql语句到mysql服务器,执行
1.2 什么是JDBC?
使用java程序发送sql语句到数据库服务器端执行,这叫用到了JDBC技术!!!!
jdbc是Oracle-Sun公司设计的一套专门用于java程序操作数据库的接口。
1.3 使用jdbc发送sql条件
连接mysql数据库:
数据库主机
端口
数据库用户名
数据库密码
连接的数据库
原理图




1.4 JDBC的核心API
|-Driver接口: 数据库驱动程序的接口,所有具体数据库厂商需要的驱动程序需要实现次接口。
Connection connect(String url, Properties info) 用于获取数据库连接
|-Connection接口:与具体的数据库的连接对象。
Statement createStatement() 创建一个静态sql语句对象
PreparedStatement prepareStatement(String sql) 创建预编译的sql语句对象
CallableStatement prepareCall(String sql) 创建存储过程的sql语句对象
|-Statement接口:用于执行静态 SQL 语句
int executeUpdate(String sql) 执行更新操作的sql语句 (create/alter/drop/insert/update/delete)
ResultSet executeQuery(String sql) 执行查询操作的sql语句
(select)
|- PreparedStatement接口:用于执行预编译的 SQL 语句(是Statement的子接口)
int executeUpdate() 执行更新操作的sql语句
ResultSet executeQuery() 执行查询操作的sql语句
|- CallableStatement接口:用于执行 SQL 存储过程的接口(是PreparedStatement的子 接口)
ResultSet executeQuery() 执行存储过程的sql语句
|- ResultSet接口:结果集对象。 存储所有数据库查询的结果,用该对象进行数据遍历。
boolean next() : 把光标移动到下一行。如果下一行有数据,返回true,如果没有下一行数 据,返回false。
getXXX(列索引|列字段名称): 获取字段的数据
2 Statement对象执行SQL操作
2.1 执行DDL操作
/**
* 通过jdbc执行DDL语句
* @author APPle
*
*/
public class Demo1 {
private static String url = "jdbc:mysql://localhost:3306/day17";
private static String user = "root";
private static String password = "root";
public static void main(String[] args){
Connection conn = null;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
stmt = conn.createStatement();
String sql = "CREATE TABLE student(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),gender VARCHAR(2))";
int count = stmt.executeUpdate(sql);
System.out.println("影响了"+count+"行");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
2.2 执行DML操作
/**
* 通过jdbc执行DML语句(insert/update/delete)
* @author APPle
*
*/
public class Demo2 {
private static String url = "jdbc:mysql://localhost:3306/day17";
private static String user = "root";
private static String password = "root";
/**
* 执行插入操作
*/
@Test
public void test1(){
Connection conn = null;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
stmt = conn.createStatement();
String sql = "INSERT INTO student(NAME,gender) VALUES('张三','男')";
int count = stmt.executeUpdate(sql);
System.out.println("影响了"+count+"行");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
/**
* 执行更新操作
*/
@Test
public void test2(){
Connection conn = null;
Statement stmt = null;
String name = "陈六";
int id=2;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
stmt = conn.createStatement();
String sql = "UPDATE student SET NAME='"+name+"' WHERE id="+id+"";
int count = stmt.executeUpdate(sql);
System.out.println("影响了"+count+"行");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
/**
* 执行删除操作
*/
@Test
public void test3(){
Connection conn = null;
Statement stmt = null;
int id=2;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
stmt = conn.createStatement();
String sql = "DELETE FROM student WHERE id="+id+"";
int count = stmt.executeUpdate(sql);
System.out.println("影响了"+count+"行");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
2.3 执行DQL查询操作
/**
* 使用jdbc执行DQL语句(select)
* @author APPle
*
*/
public class Demo3 {
private static String url = "jdbc:mysql://localhost:3306/day17";
private static String user = "root";
private static String password = "root";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
stmt = conn.createStatement();
String sql = "SELECT * FROM student";
rs = stmt.executeQuery(sql);
/**
* 注意:
* 1)如果光标在第一行之前,使用rs.getXX()获取列值,报错:Before start of result set
* 2)如果光标在最后一行之后,使用rs.getXX()获取列值,报错:After end of result set
*/
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
String gender = rs.getString("gender");
System.out.println(id+"\t"+name+"\t"+gender+"\t");
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
if(rs!=null)
try {
rs.close();
} catch (SQLException e1) {
e1.printStackTrace();
throw new RuntimeException(e1);
}
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
3 PreparedStatement对象执行SQL操作
/**
* 使用PreparedStatement执行sql语句
* @author APPle
*
*/
public class Demo1 {
/**
* 插入操作
*/
@Test
public void test1(){
Connection conn = null;
PreparedStatement stmt = null;
try{
conn = JdbcUtil.getConnection();
String sql = "INSERT INTO student(NAME,gender) VALUES(?,?)";
stmt = conn.prepareStatement(sql);
/**
* 参数一: 参数位置。从1开始
* 参数二: 参数实际值
* 注意: 所有参数必须要赋值
*/
stmt.setString(1, "rose");
stmt.setString(2, "女");
int count = stmt.executeUpdate();
System.out.println(count);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
JdbcUtil.close(conn, stmt, null);
}
}
/**
* 修改操作
*/
@Test
public void test2(){
Connection conn = null;
PreparedStatement stmt = null;
String name = "jacky";
int id = 8;
try{
conn = JdbcUtil.getConnection();
String sql = "UPDATE student SET NAME=? WHERE id=?";
stmt = conn.prepareStatement(sql);
stmt.setString(1,name);
stmt.setInt(2, id);
int count = stmt.executeUpdate();
System.out.println(count);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
JdbcUtil.close(conn, stmt, null);
}
}
/**
* 删除操作
*/
@Test
public void test3(){
Connection conn = null;
PreparedStatement stmt = null;
int id = 8;
try{
conn = JdbcUtil.getConnection();
String sql = "DELETE FROM student WHERE id=?";
stmt = conn.prepareStatement(sql);
stmt.setObject(1, id);
int count = stmt.executeUpdate();
System.out.println(count);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
JdbcUtil.close(conn, stmt, null);
}
}
/**
* 查询操作
*/
@Test
public void test4(){
Connection conn = null;
PreparedStatement stmt = null;
String name = "张%";
try{
conn = JdbcUtil.getConnection();
String sql = "SELECT * FROM student WHERE NAME LIKE ?";
stmt = conn.prepareStatement(sql);
stmt.setObject(1, name);
ResultSet rs = stmt.executeQuery();
while(rs.next()){
int id = rs.getInt("id");
String nameStr = rs.getString("name");
String gender = rs.getString("gender");
System.out.println(id+"\t"+nameStr+"\t"+gender+"\t");
}
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
JdbcUtil.close(conn, stmt, null);
}
}
}
==============Statement和PreparedStatement的区别==========================================
一、语法结构不同
1)Statment执行静态sql语句,且sql可以拼接。
2)PreparedStatement可以先执行预编译的sql语句,在预编译sql语句中使用?进行参数占位,后面 在进行参数赋值
二、原理不同
1)Statement不能进行sql缓存
2)而PreparedStatement可以进行sql缓存,执行效率会比Statement快!!!
三、安全性不同
1)Statement存在sql注入的风险
2)而PreparedStatement可以有效防止用户注入。
4 CallableStatement对象执行存储过程
4.1 执行带输入参数的存储过程
/**
* 执行带有输入参数存储过程
*/
@Test
public void test1(){
Connection conn = null;
CallableStatement stmt = null;
ResultSet rs = null;
try{
conn = JdbcUtil.getConnection();
String sql = "CALL pro_findById(?)";
stmt = conn.prepareCall(sql);
stmt.setInt(1, 4);
rs = stmt.executeQuery();
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
String gender = rs.getString("gender");
System.out.println(id+"\t"+name+"\t"+gender+"\t");
}
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
JdbcUtil.close(conn, stmt, rs);
}
}
4.2 执行带有输出参数的存储过程
/**
* 执行带有输出参数存储过程
*/
@Test
public void test2(){
Connection conn = null;
CallableStatement stmt = null;
try{
conn = JdbcUtil.getConnection();
String sql = "CALL pro_findById2(?,?)";
stmt = conn.prepareCall(sql);
stmt.setObject(1, 4);
/**
* 参数一: 参数位置
* 参数二: 表示存储过程中的OUT参数的数据库类型
*/
stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
stmt.executeQuery();
/**
* 如何获取存储过程的返回值:OUT参数值。使用getXXX方法
*/
String name = stmt.getString(2);
System.out.println("结果:"+name);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
JdbcUtil.close(conn, stmt, null);
}
}
5 使用类路径加载资源文件
/**
* 使用类路径的方式加载db.properties文件
*/
Class clazz = JdbcUtil.class;
InputStream in = clazz.getResourceAsStream("/db.properties");
prop.load(in);
Class.getResourceAsStream("/db.properties");
Class.getResourceAsStream("db.properties");
这里的 斜杠 / 表示当前项目的类路径的根目录。
当前项目是java项目,/ 在项目的bin目录下
当前项目是web项目,/在项目的WEB-INF/classes目录下
注意: 无论是java项目还是web项目,在开发时如果把资源文件放在src下,那么src下的文件都会拷贝到类路径的根目录下。