JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序,同时,JDBC也是个商标名。
一、:JDBC的简单使用
首先JDBC是一个接口的集合,是用来控制SQL语句的,要导入一些包,本例子中使用的是junit.Test 的测试方式
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
// 测试方法,方法必须是public void,再加上一个@Test,然后选中方法,右键run as junit
import org.junit.Test;
public class Demo {
@Test
//发送插入语句
public void fun1() throws Exception{
//1 导入驱动类库
//2 注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//3 连接数据库
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day05", "root", "1234");
//4 操作数据库
Statement st = conn.createStatement();
String sql = " INSERT INTO `t_user` "+
" VALUES (NULL, 'tom', 18)" ;
st.executeUpdate(sql);
//5 关闭资源
st.close();
conn.close();
}
@Test
//发送查询语句
public void fun2() throws Exception{
//1 导入驱动类库
//2 注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//3 连接数据库,最后的day05代表的是数据库的意思
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day05", "root", "7q7q77qq");
//4 操作数据库
Statement st = conn.createStatement();
String sql = " select * from t_user " ;
ResultSet rs = st.executeQuery(sql);
//遍历结果集中的内容并打印
while(rs.next()){
String name = rs.getString("name");
int id = rs.getInt("id");
int age = rs.getInt("age");
System.out.println(name+"==>"+age+"==>"+id);
}
//5 关闭资源
st.close();
conn.close();
}
}
二、:JDBC驱动的注册
推荐使用的是第二种方式,第一种在静态代码块调用了,静态代码块在类加载时被调用,所以我们加载类就可以了
package cn.itcast.b_dm;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
//DriverManager细节
public class Demo {
@Test
public void fun1() throws Exception{
// 注册驱动
//注册方式1:不推荐 => 驱动实现类中 的静态代码以及调用过
// DriverManager.registerDriver(driver);
//注册方式2:推荐
Class.forName("com.mysql.jdbc.Driver");
}
@Test
public void fun2() throws Exception{
// 获得连接
DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/day05", "root", "1234");
//url完整 格式: 大协议:子协议://IP地址:端口号/库名?参数键=参数值
//完整: jdbc:mysql://127.0.0.1:3306/day05?useUnicode=true&characterEncoding=utf8
//简单: <span style="white-space:pre"> </span> jdbc:mysql:///day05?useUnicode=true&characterEncoding=utf8
}
}
三、:JDBC四种执行方式
package cn.itcast.c_st;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
//Statement细节
public class Demo {
@Test
//execute 原始,增删改查都可以 返回值 true=> 查询有结果集 | false=> 查询没有结果集
//executeBatch 批量执行sql
//executeUpdate 执行增删改
//executeQuery 执行查询
public void fun1() throws Exception{
//1 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2 获得连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day05", "root", "1234");
//3 创建Statement
Statement st = conn.createStatement();
//4 书写sql
String sql = " INSERT INTO `t_user` "+
" VALUES (NULL, 'jerry', 16)" ;
//5 执行sql
boolean result = st.execute(sql);
System.out.println(result);//false
//6关闭资源
st.close();
conn.close();
}
@Test
public void fun2() throws Exception{
//1 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2 获得连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day05", "root", "1234");
//3 创建Statement
Statement st = conn.createStatement();
//4 书写sql
String sql = "select * from t_user" ;
//5 执行sql
boolean result = st.execute(sql);
if(result){
ResultSet rs = st.getResultSet();
System.out.println(rs);
}
//6关闭资源
st.close();
conn.close();
}
@Test
//executeUpdate
public void fun3() throws Exception{
//1 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2 获得连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day05", "root", "1234");
//3 创建Statement
Statement st = conn.createStatement();
//4 书写sql
String sql = " INSERT INTO `t_user` "+
" VALUES (NULL, 'jack', 20)" ;
//5 执行sql
int row = st.executeUpdate(sql);
if(row!=1){
throw new RuntimeException("插入失败!");
}
System.out.println(row);//1
//6关闭资源
st.close();
conn.close();
}
@Test
//executeQuery
public void fun4() throws Exception{
//1 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2 获得连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day05", "root", "1234");
//3 创建Statement
Statement st = conn.createStatement();
//4 书写sql
String sql = "select * from t_user" ;
//5 执行sql
ResultSet rs = st.executeQuery(sql);
//遍历rs
System.out.println(rs);
//6关闭资源
st.close();
conn.close();
}
}
四、:JDBC修改数据库
下面使用的是updateString的方式来修改的
package cn.itcast.d_rs;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
//ResultSet细节
// 2.结果集反向修改数据库
public class Demo3 {
@Test
public void fun1() throws Exception{
//1 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2 获得连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day05", "root", "1234");
//3 创建Statement
Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
//4 书写sql
String sql = "select * from t_user" ;
//5 执行sql
ResultSet rs = st.executeQuery(sql);
//使用结果集 反向修改数据库
rs.next();//将光标移动到第一行
rs.updateString("name", "汤姆");// 修改第一行name列的值为中文汤姆
rs.updateRow();// 确认修改
//6关闭资源
st.close();
conn.close();
}
}
五、:JDBC中的工具类
通过使用工具类来导入db.properties中的数据来获得用户名密码等信息,最终获得连接的过程
package cn.itcast.e_tool;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils {
private static String driver;
private static String url;
private static String user;
private static String password;
static{
try {
//0读取配置文件
Properties prop = new Properties();
InputStream is = new FileInputStream("src/db.properties");
prop.load(is);
is.close();
driver = prop.getProperty("driver");
url = prop.getProperty("url");
user = prop.getProperty("user");
password = prop.getProperty("password");
//1 注册驱动
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
//1 获得连接
public static Connection getConnection(){
Connection conn = null;
try {
//2 获得连接
conn = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("创建连接失败!");
}
return conn;
}
//2 释放资源
//1> 参数可能为空
//2> 调用close方法要抛出异常,确保即使出现异常也能继续关闭
//3>关闭顺序,需要从小到大
public static void close(Connection conn , Statement st , ResultSet rs){
try {
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(st!=null){
st.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
System.out.println(getConnection());
}
}
六、:SQL注入问题
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。下边的fun1()就是一个SQL注入的问题,fun2使问题得以解决了。
package cn.itcast.f_ps;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
import cn.itcast.e_tool.JDBCUtils;
public class Demo {
@Test
//演示使用Statement对象,sql注入问题
public void fun1() throws Exception{
String name ="xxx' OR 1=1 -- ";
String password ="1234";
//1 获得连接
Connection conn= JDBCUtils.getConnection();
//2 获得Statement
Statement st = conn.createStatement();
//3 拼装sql语句
String sql = "SELECT * FROM t_user WHERE NAME='"+name+"' AND PASSWORD='"+password+"';";
//4 执行sql并拿到结果
ResultSet rs = st.executeQuery(sql);
//5 根据结果判断是否登录成功
if(rs.next()){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
//6关闭资源
JDBCUtils.close(conn, st, rs);
}
@Test
//演示使用PrepareStatement对象,解决sql注入问题
public void fun2() throws Exception{
String name ="xxx' OR 1=1 -- ";
String password ="1234";
//1 获得连接
Connection conn= JDBCUtils.getConnection();
//2 拼装sql语句
String sql = "SELECT * FROM t_user WHERE NAME=? AND PASSWORD=?";
//3 获得PrepareStatement
PreparedStatement ps = conn.prepareStatement(sql);
//4 设置参数到ps对象中
ps.setString(1, name);
ps.setString(2, password);
//5 运送参数,执行sql并拿到结果
ResultSet rs = ps.executeQuery();
//5 根据结果判断是否登录成功
if(rs.next()){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
//6关闭资源
JDBCUtils.close(conn, ps, rs);
}
}
最后的这个PreparedStatement是有点问题的,正在努力解决中。