一、JDBC
java database connection
Java提供的是连接数据库的规范、规则,提供的只是接口,因为数据库不同,具体的实现方式不同,所以java只制定规则,各个数据库厂商提供接口的实现类
lib — library ---- 库
(1)修改数据库数据
1.实现需要准备mysql的驱动jar包:jar包中都是jdbc提供的接口的实现类
2.加载mysql驱动,把mysql的驱动类加载到内存(反射)
3.创建和mysql的连接,返回一个和数据库的连接对象 多态
4.执行数据库操作 Statement对象具备执行sql语句的功能
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1.首先需要准备mysql的驱动jar包:jar包中都是JDBC提供的接口的实现类
//2.加载mysql驱动 把MySQL的驱动类加载到内存 Driver.class
Class.forName("com.mysql.cj.jdbc.Driver");//Driver.class com.mysql.jdbc.Driver
//3.创建和mysql的连接,返回一个和数据库的连接对象 多态
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bg1?characterEncoding=utf8&useSSL=false&serverTimezone=UTC", "root", "root");
//4.执行数据库操作 Statement对象具备执行sql语句的功能
Statement statement = connection.createStatement();
//定义sql语句
String sql="update stu set gender='female' where sid='S_1003'";
int i = statement.executeUpdate(sql);//返回值是sql语句执行时受影响的行数
if(i>0)
System.out.println("数据修改成功");
statement.close();
connection.close();
}
}
(2)查询数据库数据
查询会产生结果集ResultSet,根据字段名得到游标指向的记录中的数据,再将结果集遍历出来(只有查询操作比较麻烦)
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/bg1?characterEncoding=utf8&useSSL=false&serverTimezone=UTC", "root", "root");
Statement statement = connection.createStatement();
String sql="select * from emp";
//结果集
ResultSet resultSet = statement.executeQuery(sql);
//boolean next = resultSet.next();//每next一次,游标下移,如果游标指向的是一条记录,那么返回true,否则返回false
while(resultSet.next()){
int empno = resultSet.getInt("empno");//根据字段名得到游标指向的记录中的数据
String ename=resultSet.getString("ename");
String job=resultSet.getString("job");
int mgr=resultSet.getInt("mgr");
Date hiredate = resultSet.getDate("hiredate");
double sal=resultSet.getDouble("sal");
double comm=resultSet.getDouble("comm");
int deptno=resultSet.getInt("deptno");
System.out.println(empno+","+ename+","+job+","+mgr+","+hiredate+","+sal+","+comm+","+deptno);
}
resultSet.close();
statement.close();
connection.close();
}
}
(3)向数据库添加数据
public class Demo3 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bg1?characterEncoding=utf8&useSSL=false&serverTimezone=UTC","root","root");
Statement statement = conn.createStatement();
String sql="insert into stu values('S_1012','小花',20,'female')";
int i = statement.executeUpdate(sql);//返回值是sql语句执行时受影响的行数
if(i>0)
System.out.println("添加成功");
statement.close();
conn.close();
}
}
(4)封装工具类
从上面的几个例子可以看出,每个操作都会产生很多重复的代码,下面进行处理——封装工具类
封装工具类:
把数据库相关的配置提取到db.properties中
定义工具类:
定义存储数据库配置的四个静态的成员变量
因为加载数据库驱动只需啊哟执行一次,所以把加载配置文件信息的功能写在静态代码块中
ResourceBundle bundle = ResourceBundle.getBundle("db");
driver = bundle.getString("db.driver");
url = bundle.getString("db.url");
username = bundle.getString("db.username");
password = bundle.getString("db.password");
获取和数据库的连接对象,Connection的子类对象,需要多次获取Connection的子类对象,所以提取成一个public的静态方法
public Connection getConnection()
{
DriverManager.getConnection(url,username,password);
}
关闭的功能
public void close(ResuleSet rs,Statement st,Connection conn)
{
if(rs!=null)
rs.close();
if(st!=null)
st.close();
if(conn!=null)
conn.close();
}
目录结构如下:
db.properties文件
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/bg1?characterEncoding=UTF8&useSSL=false&serverTimezone=UTC
db.username=root
db.password=123456
DBUtil.java文件
package util;
import java.sql.*;
import java.util.ResourceBundle;
public class DBUtil {
// 定义四个变量存放四个配置
private static String driver;
private static String url;
private static String username;
private static String password;
static {
//随着类的加载而执行,只执行一次,且优先于main执行
ResourceBundle bundle = ResourceBundle.getBundle("db");
driver = bundle.getString("db.driver");
url = bundle.getString("db.url");
username = bundle.getString("db.username");
password = bundle.getString("db.password");
try {
//驱动只需要加载一次
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 获取数据库连接的方法
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
public static void close(ResultSet resultSet, Statement statement, Connection connection) throws SQLException {
if(resultSet!=null)
resultSet.close();
if(statement!=null)
statement.close();
if(connection!=null)
connection.close();
}
}
(5)删除数据库数据
利用工具类
public class Demo4 {
public static void main(String[] args) throws SQLException {
Connection connection = DBUtil.getConnection();
Statement statement = connection.createStatement();
String sql="delete from stu where sid='S_1012'";
int i = statement.executeUpdate(sql);
if(i>0)
System.out.println("删除成功");
DBUtil.close(null,statement,connection);
}
}
获取和数据库的连接对象,Connection的子类对象,需要多次获取Connection的子类对象,所以提取成一个public的静态方法
二、批处理
statement.executeBatch() ----- 其实就是将多条SQL语句存储起来一起执行
bath 一捆
public class Demo5 {
public static void main(String[] args) throws SQLException {
//批处理
Connection conn= DBUtil.getConnection();
Statement statement = conn.createStatement();
//批量执行sql语句
int num=1;
while(num<=200)
{
String sql="insert into tb3 values(null,'xiaobai"+num+"','m')";
statement.addBatch(sql);
if(num%30==0)
statement.executeBatch();//批量执行
num++;
}
statement.executeBatch();
DBUtil.close(null,statement,conn);
}
}
三、防止SQL注入
public class Demo6 {
public static void main(String[] args) throws IOException, SQLException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("输入用户名");
String name=br.readLine();
System.out.println("输入密码");
String pwd=br.readLine();
Connection conn= DBUtil.getConnection();
Statement statement = conn.createStatement();
//根据用户名和密码去表中查询,如果查询出来记录说明登录成功,否则失败
//SQL注入 hehe' or '1'='1
//user_name='yutao' and user_pwd='hehe' or '1'='1'
String sql="select * from bank_account where user_name='"+name+"' and user_pwd='"+pwd+"'";
ResultSet resultSet = statement.executeQuery(sql);
if(resultSet.next())
System.out.println("success");
else
System.out.println("用户名或密码错误!");
DBUtil.close(resultSet,statement,conn);
}
}
SQL注入: 使用Statement对象执行sql语句,存在安全隐患,
使用PreparedStatement解决SQL注入的问题
String sql="select * from emp where empno=?"
PreparedStatement stat=conn.prepareStatement(sql); //此行代码编译了 sql语句 PreparedStatement接口是Statement接口的子接口
stat.setInt(1,7369); 给占位符指定值
ResultSet rs = stat.executeQuery();
public class Demo7 {
public static void main(String[] args) throws IOException, SQLException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("输入用户名");
String name=br.readLine();
System.out.println("输入密码");
String pwd=br.readLine();
Connection conn= DBUtil.getConnection();
String sql="select * from bank_account where user_name=? and user_pwd=?";//?是占位符
PreparedStatement preparedStatement = conn.prepareStatement(sql);//sql已经预编译了,PreparedStatement是Statement的子接口
//通过PreparedStatement对象给两个占位符指定具体的值
preparedStatement.setString(1,name);
preparedStatement.setString(2,pwd);
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next())
System.out.println("success");
else
System.out.println("用户名或密码错误!");
DBUtil.close(resultSet,preparedStatement,conn);
}
}
四、总结
JDBC: java database connection JDK 提供的
java 提供了连接数据库的API,使用api实现对数据库中数据的操作
JDK提供的都是接口,也就是规则,各个数据库厂商提供接口的实现类
Connection
Class.forName("com.mysql.cj.jdbc.Driver")
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bg1?
characterEncoding=utf8&useSSL=false&serverTimezone=UTC","root","root");
Statement stat = conn.createStatement();
封装工具类:
把数据库相关的配置提取到 db.properties文件中
定义工具类:
定义存储数据库配置的四个静态的成员变量
因为加载数据库驱动只需要执行一次,所以把加载驱动的代码写在静态代码块中
获取配置文件中的信息,也只需执行一次,所以把获取配置文件信息的功能写在静态代码块中
ResourceBundle bundle=ResourceBundle.getBundle("db");
driver=bundle.getString("db.driver");
url=bundle.getString("db.url");
username=bundle.getString("db.username");
password=bundle.getString("db.password");
//获取和数据库的连接对象,Connection的子类对象,需要多次获取Connection的子类对象,所以提取成一个public的静态方法
public Connection getConnection()
{
DriverManager.getConnection(url,username,password);
}
//关闭的功能
public void close(ResuleSet rs,Statement st,Connection conn)
{
if(rs!=null)
rs.close();
if(st!=null)
st.close();
if(conn!=null)
conn.close();
}
以下都是jdk提供的接口:
Connection
Statement
ResultSet
PreparedStatement
SQL注入: 使用Statement对象执行sql语句,存在安全隐患,
使用PreparedStatement解决SQL注入的问题
String sql="select * from emp where empno=?"
PreparedStatement stat=conn.prepareStatement(sql); //此行代码编译了 sql语句
PreparedStatement接口是Statement接口的子接口
stat.setInt(1,7369); 给占位符指定值
ResultSet rs = stat.executeQuery();