1.JDBC介绍
JDBC全称为Java Data Base Connectivity,中文为Java数据库连接,顾名思义它就是Java与数据库的连接的桥梁或者说是一个插件。著名的sun公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范(接口),称之为JDBC。
在开发jdbc之前需要下载相应的数据库驱动
下载地址https://mvnrepository.com/artifact/mysql/mysql-connector-java,其中有很多版本,我下载的是mysql-connector-java-5.1.47.jar,然后把这个jar包放到lib目录下,如图
2.JDBC的常用步骤
代码及注释如下
public class JdbcTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取与数据库的连接
String username="root";
String password="123456";
String url="jdbc:mysql://localhost:3306/jdbcstudy";
Connection connection = DriverManager.getConnection(url, username, password);
//3.创建向数据库发送sql的statement对象
//createStatement():创建向数据库发送sql的statement对象
Statement statement = connection.createStatement();
String sql="select id,name,password,email from users";
//excuteQuery(String sql):用于向数据发送查询语句
//4.向数据库发送sql
ResultSet resultSet = statement.executeQuery(sql);
//ResultSet类讲解:next()方法:移动到下一行
//5.取出结果集
while(resultSet.next()){
System.out.println(resultSet.getObject("id"));
System.out.println(resultSet.getObject("name"));
System.out.println(resultSet.getObject("password"));
System.out.println(resultSet.getObject("email"));
}
//6.释放资源
resultSet.close();
statement.close();
connection.close();
}
}
JDBC中常用类讲解
**DriverManager:**用于加载驱动,并创建与数据库的连接,获得connection接口;
推荐使用 Class.forName(“com.mysql.jdbc.Driver”);
Connection(接口):建立数据库连接的一个接口,主要的常用方法:
createStatement():创建向数据库发送sql的statement对象
prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象
prepareCall(sql):创建执行存储过程的callableStatement对象。
setAutoCommit(boolean autoCommit):设置事务是否自动提交
commit() :在链接上提交事务
rollback() :在此链接上回滚事务
Statement(接口):用于向数据库发送sql语句;常用方法:
executeQuery(String sql) :用于向数据发送查询语句。
executeUpdate(String sql):用于向数据库发送insert、update或delete语句
ResultSet(接口):结果集,statement发送sql语句,得到的结果封装在ResultSet中。
3.JDBC实现对数据库的增删改查
先需要创建一个简单的数据库,用来作练习
#创建jdbcstudy数据库
create database jdbcStudy character set utf8 collate utf8_general_ci;
use jdbcStudy;
#创建users表
create table users(
id int primary key,
name varchar(40),
password varchar(40),
email varchar(60),
birthday date
);
#插入数据
insert into users(id,name,password,email,birthday) values(1,'zhansan','123456','zs@sina.com','1980-12-04');
insert into users(id,name,password,email,birthday) values(2,'lisi','123456','lisi@sina.com','1981-12-04');
insert into users(id,name,password,email,birthday) values(3,'wangwu','123456','wangwu@sina.com','1979-12-04');
用JDBC的常用步骤来insert新的数据
public class JdbcTest2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
String username="root";
String password="123456";
String url="jdbc:mysql://localhost:3306/jdbcstudy";
Connection connection = DriverManager.getConnection(url, username, password);
Statement statement = connection.createStatement();
String sql="insert into users(id,NAME,PASSWORD,email,birthday) VALUES(4,'libai','123456','wangwu@sina.com','1979-12-04');";
int i = statement.executeUpdate(sql);
if (i>0){
System.out.println("插入成功");
}
//释放资源
statement.close();
connection.close();
}
}
因为每次进行数据库的增删改查操作是,都要进行加载驱动,获取与数据库的连接和释放资源这些重复步骤,所以为了方便,就创建了一个工具类JDBCUtils,增删改查操作需要时进行调用。该工具类代码如下
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static String driver = null;
private static String username = null;
private static String password = null;
private static String url = null;
static {
try {
//加载配置文件
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(is);
//读取配置文件
driver = properties.getProperty("driver");
username = properties.getProperty("username");
password = properties.getProperty("password");
url = properties.getProperty("url");
//加载数据驱动
Class.forName(driver);
}catch (IOException e){
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取数据库连接对象
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url,username,password);
}
//释放资源
public static void closeAll(ResultSet resultSet, Statement statement, Connection connection){
if (resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
还需要在同目录下创建一个配置文件db.properties,文件里的数据如下
(当然也可以不需要配置文件,在工具类中将下面的数据写好就行,配置文件显得代码高级,可读性强)
driver = com.mysql.jdbc.Driver
username = root
password = 123456
url = jdbc:mysql://localhost:3306/jdbcstudy?useSSL=true
现在就可以利用此工具类进行数据库的增删改查了。示例如下:
import jdk.nashorn.internal.scripts.JD;
import org.junit.Test;
import utils.JDBCUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//测试jdbc的增删改查
public class Demo1 {
@Test
//插入语句
public void insert() throws SQLException {
//1.获取数据库的连接
Connection connection=JDBCUtils.getConnection();
//2.创建statement对象
Statement statement=connection.createStatement();
//3.编写sql语句
String sql="INSERT INTO users(id,NAME,PASSWORD,email,birthday) VALUES(5,'wangwu','123456','wangwu@sina.com','1979-12-04');";
//4.执行sql语句
int i=statement.executeUpdate(sql);
//5.释放资源
JDBCUtils.closeAll(null,statement,connection);
}
@Test
public void delete() throws SQLException {
//1.获取数据库的连接
Connection connection=JDBCUtils.getConnection();
//2.创建statement对象
Statement statement=connection.createStatement();
//3.编写sql语句
String sql="delete from users where id=5";
//4.执行sql语句
int i = statement.executeUpdate(sql);
if (i>0) {
System.out.println("删除成功");
}
//5.释放资源
JDBCUtils.closeAll(null,statement,connection);
}
@Test
public void update() throws SQLException {
Connection connection = JDBCUtils.getConnection();
Statement statement = connection.createStatement();
String sql="update users set name='qinjiang' where id=4";
int i = statement.executeUpdate(sql);
if (i>0){
System.out.println("修改成功");
}
JDBCUtils.closeAll(null,statement,connection);
}
@Test
public void query() throws SQLException {
// 1.获取数据库的连接
Connection connection = JDBCUtils.getConnection();
Statement statement = connection.createStatement();
String sql="select*from users";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getInt("id"));
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getString("password"));
System.out.println(resultSet.getString("email"));
System.out.println(resultSet.getDate("birthday"));
}
JDBCUtils.closeAll(resultSet,statement,connection);
}
}
需要注意的是这里我们用到了Java中的junit(单元测试框架),方便我们进行数据库的操作。
4.sql注入问题
在参数中设置了了一些特殊字符,是sql语句在拼接这些参数时一位特殊字符的原因改变了sql语句原来的规则,从而对数据进行操作。
解决方法:可使用preparedStatement 解决sql注入问题,运行在sql中参数以 ?占位符的方式来表示。其解决方法的代码如下所示:
import utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
//防止sql注入
public class Demo3 {
public static void main(String[] args) throws SQLException {
//1.获取数据库连接
Connection connection = JDBCUtils.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("select * from users where id = ? and name = ? ");
preparedStatement.setInt(1,4);//从一开始,传入的值为4
preparedStatement.setString(2,"liudehua");//从2开始,传入的值为liudehua
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getString("password"));
}
JDBCUtils.closeAll(resultSet,preparedStatement,connection);
}
}
其中preparedStatement.setxxx(int index,要放入的值),第一个 参数index是指第几个问号,该参数从1开始计数。第二个参数是给?的位置传入的值。
语句中有几个问号,就需要传递几个参数。比如上面代码中有两个问号,就需要传递两个参数 preparedStatement.setInt(1,4); preparedStatement.setString(2,“liudehua”)
5.preparedStatement(推荐使用)和statement的区别
相同点:都是用来执行sql语句的
不同点:statement不安全,不能预编译sql,不能使用占位符,容易造成sql语句拼接错误;preparedStatement 安全,预编译sql语句,可以使用?占位符
statement先写sql语句再执行,statement.execute(sql);
preparedStatement 直接编译sql,调用方法执行,preparedStatement.execute()。
preparedStatements是Statement的子类
它的实际对象可以通过Connection.prearedStatement()方法获得,相对于Statement对象而言,Prepared Statement可以避免sql注入的问题
Statement会使数据库频繁编译sql,可能造成数据库缓冲区溢出,PreparedStatement可对sql进行预编译,从而提高数据库的执行效率,并且PreparedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写
6.事务
事务是应用程序中一系列严密的操作,所有操作必须 成功完成,否则在每个操作中所作的所有更改都会被撤销。也就是事务具有原子性,一个事务中的一系列的操作要么全部完成,要么一个都不做。
开启事务 setAutoCommit(false);
提交事务 commit ;
回滚事务 rollback
#开启事务后,如果不提交事务,那么所有的操作在mysql连接断开后,会回复到最开始的样子;
#开启事务后,更新了数据,不想更新了,可以选择回滚
事务的结束有两种,当事务中的所有步骤全部成功执行时,事务提交;如果其中一个步骤失败,将发生回滚操作,撤销之前到事务开始时的所有操作
事务具有四个特性,原子性(Atomicity),一致性(Consistency),隔离性(Isolation)和持续性(Durability),简称为ACID特性。
- 原子性:事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
- 一致性:事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统运行中发生故障,有些事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。
- 隔离性:一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能相互干扰
- 持续性:也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该时永久性的,接下来的其他操作或故障不应该对其执行结果有任何影响。
7.数据库备份
1.直接在data文件夹中拷贝数据
2.使用工具mysqldump进行数据备份