代码链接:https://download.csdn.net/download/qq_52354698/86478243?spm=1001.2014.3001.5501
Java 直接访问数据库
通过 JDBC 访问数据库
说明:JDBC是Java提供一套用于数据库操作的接口API, Java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。
JDBC API是一系列的接口, 它统一和规范 了应用程序与数据库的连接、 执行SQL语句,并到得到返回结果等各类操作,相关类和接口在java.sql与javax.sql包中。
通过JDBC对表actor进行添加、删除、修改
create table actor (
id int primary key auto_increment,
name varchar(32) not null default ' ',
sex char(1) not null default '女',
borndate datetime ,
phone varchar(12));
前置工作:在项目下创建一个文件夹libs,将mysql.jar拷贝到该目录下,点击add to project… 加入到项目中
jdbc:mysql
:规定好表示协议,通过jdbc的方式连接mysql
localhost
:主机,可以是ip地址
3306
:表示mysql监听的端口号
qdu_01
:连接到mysql的那个数据库
String url = "jdbc:mysql://localhost:3306/qdu_01";
mysql的连接本质上就是前面学过的socket连接
package com.qdu.jdbc;
import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* @author dell
* @version 1.0
*/
public class Jdbc01 {
public static void main(String[] args) throws SQLException {
//前置工作:在项目下创建一个文件夹libs,将mysql.jar拷贝到该目录下,点击add to project.. 加入到项目中
//注册驱动
Driver driver = new Driver();
//得到连接
String url = "jdbc:mysql://localhost:3306/qdu_01?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
//将用户名和密码放入到Properties对象
Properties properties = new Properties();
//user 和 password 是规定好的,后面对应的就是数据库的用户名和密码
properties.setProperty("user", "root");
properties.setProperty("password", "root");
Connection connection = driver.connect(url, properties);
//执行sql
String sql = "insert into actor values(null, '刘德华', '男', '1970-01-02', '110')";
//statement 用于执行静态SQL语句并返回其生成的结果对象
Statement statement = connection.createStatement();
int rows = statement.executeUpdate(sql);//如果是dml语句,返回的就是影响的行数
System.out.println(rows > 0 ? "成功" : "失败");
//关闭连接资源
statement.close();
connection.close();
}
}
可能存在的问题:对于mysql.jar包的导入要首先确定自己的mysql的版本,最后是统一版本,同时对于url的设置,6.0之前和6.0之后会有所不同,如果数据库连接失败的话,最好查看一下是否符合版本要求
静态加载,灵活性差,依赖性强
Driver driver = new Driver();
String url = "jdbc:mysql://localhost:3306/qdu_01?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "root");
Connection connection = driver.connect(url, properties);
动态加载,更加的灵活,减少依赖性
Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
String url = "jdbc:mysql://localhost:3306/qdu_01?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "root");
使用DriverManger替换Driver
public void connect03() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
String url = "jdbc:mysql://localhost:3306/qdu_01?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
String user = "root";
String password = "root";
DriverManager.registerDriver(driver);//注册Driver驱动
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
使用 Class.forName 自动完成注册驱动
在加载 Driver 类时,会自动完成注册
使用最多
public void connect04() throws ClassNotFoundException, SQLException {
//使用反射加载Driver类
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/qdu_01?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
mysql驱动5.1.6之后就不需要再写 Class.forName(“com.mysql.jdbc.Driver”); 了
使用配置文件,连接数据库更灵活
最建议使用
user=root
password=root
url=jdbc:mysql://localhost:3306/qdu_01?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
driver=com.mysql.jdbc.Driver
public void connect() throws IOException, SQLException {
//通过Properties对象获取配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
package com.qdu.jdbc;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
/**
* @author dell
* @version 1.0
*/
public class ResultSet_ {
public static void main(String[] args) throws IOException, SQLException {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();
String sql = "select id, name, sex, borndate from actor";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){//让光标向后移动,如果没有更多记录,返回false
int id = resultSet.getInt(1);//获取该行的第一列数据
String name = resultSet.getString(2);
String sex = resultSet.getString(3);
Date date = resultSet.getDate(4);
System.out.println(id + " " + name + " " + sex + " " + date);
}
resultSet.close();
statement.close();
connection.close();
}
}
package com.qdu.jdbc.statement_;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;
/**
* @author dell
* @version 1.0
*/
public class Statement_ {
public static void main(String[] args) throws IOException, SQLException {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入管理员的名字:");
//用户输入用户名和密码
String admin_name = scanner.nextLine();//如果希望看到SQL注入,这里需要使用nextLine(),next():接收到空格或者'就是表示结束
System.out.print("请输入管理员的密码:");
String admin_pwd = scanner.nextLine();
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();
String sql = "select name, pwd from admin where name = '" + admin_name + "' and pwd = '" + admin_pwd + "'";
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()) {
System.out.println("恭喜!登录成功!");
}else {
System.out.println("sorry!登录失败!");
}
resultSet.close();
statement.close();
connection.close();
}
}
可以控制SQL注入
package com.qdu.jdbc.preparedstatement_;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;
/**
* @author dell
* @version 1.0
*/
public class PreparedStatement_ {
public static void main(String[] args) throws IOException, SQLException {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入管理员的名字:");
//用户输入用户名和密码
String admin_name = scanner.nextLine();//如果希望看到SQL注入,这里需要使用nextLine(),next():接收到空格或者'就是表示结束
System.out.print("请输入管理员的密码:");
String admin_pwd = scanner.nextLine();
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Connection connection = DriverManager.getConnection(url, user, password);
String sql = "select name, pwd from admin where name = ? and pwd = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, admin_name);
preparedStatement.setString(2, admin_pwd);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
System.out.println("恭喜!登录成功!");
}else {
System.out.println("sorry!登录失败!");
}
resultSet.close();preparedStatement.close();
connection.close();
}
}
在jdbc操作中,获取连接和释放资源是经常使用到,可以将其封装JDBC连接的工具类JDBCUtils
package com.qdu.jdbc.utils;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
/**
* @author dell
* @version 1.0
* JDBC 的工具类,完成 mysql 的链接和关闭资源
*/
public class JDBCUtils {
//定义相关的属性(4个)
private static String user;
private static String password;
private static String url;
private static String driver;
//在static代码块中初始化
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\\mysql.properties"));
//读取相关的属性值
user = properties.getProperty("user");
password = properties.getProperty("password");
url = properties.getProperty("url");
driver = properties.getProperty("driver");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//链接数据库,返回connection
public static Connection getConnection() {
try {
return DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//关闭相关资源
//Statement 是 PreparedStatement 的父类
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
模拟经典的转账业务
create table account(
id int primary key auto_increment,
name varchar(32) not null default '',
balance double not null default 0) character set utf8;
insert into account values(null, '马云', 3000);
insert into account values(null, '马化腾', 10000);
未使用事务,执行一条 SQL 语句就会提交一条 SQL 语句(默认)
@Test
public void noTransaction() {
Connection connection = null;
String sql1 = "update account set balance = balance - 100 where id = 1";
String sql2 = "update account set balance = balance + 100 where id = 2";
PreparedStatement preparedStatement = null;
try {
connection = JDBCUtils.getConnection();
preparedStatement = connection.prepareStatement(sql1);
preparedStatement.executeUpdate();
int i = 1 / 0;//抛出一个异常,下面的代码将不会再执行
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtils.close(null, preparedStatement, connection);
}
}
使用事务,当操作出现异常时,进行回滚
@Test
public void useTransaction() {
Connection connection = null;
String sql1 = "update account set balance = balance - 100 where id = 1";
String sql2 = "update account set balance = balance + 100 where id = 2";
PreparedStatement preparedStatement = null;
try {
connection = JDBCUtils.getConnection();
//将connection设置为不自动提交
connection.setAutoCommit(false);//相当于开启了事务
preparedStatement = connection.prepareStatement(sql1);
preparedStatement.executeUpdate();
int i = 1 / 0;//抛出一个异常,下面的代码将不会再执行
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();
//在这里提交事务
connection.commit();
} catch (SQLException e) {
//我们可以在这里进行回滚,即撤销执行的SQL
//默认回滚到事务开始的状态
System.out.println("执行发生了异常,撤销执行的 SQL");
try {
connection.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
throw new RuntimeException(e);
} finally {
JDBCUtils.close(null, preparedStatement, connection);
}
}
addBatch()
:添加需要批量处理的SQL语句或参数executeBatch()
:执行批量处理语句;clearBatch()
:清空批处理包的语句向 admin2 表中添加 5000 条数据
create table admin2
(id int primary key auto_increment,
username varchar(32) not null,
password varchar(32) not null);
经典方法
@Test
public void noBatch() throws SQLException {
Connection connection = JDBCUtils.getConnection();
String sql = "insert into admin2 values (null, ?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
System.out.println("开始执行");
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
preparedStatement.setString(1, "jack" + i);
preparedStatement.setString(2, "666");
preparedStatement.executeUpdate();
}
long end = System.currentTimeMillis();
System.out.println("添加结束 " + (end - start));
JDBCUtils.close(null, preparedStatement, connection);
}
批处理
@Test
public void batch() throws SQLException {
Connection connection = JDBCUtils.getConnection();
String sql = "insert into admin2 values (null, ?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
System.out.println("开始执行");
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
preparedStatement.setString(1, "jack" + i);
preparedStatement.setString(2, "666");
//将sql语句加入到批处理包中
preparedStatement.addBatch();
//当有1000条记录时,再批量执行
if ((i + 1) % 1000 == 0) {//批量执行1000条sql
preparedStatement.executeBatch();
//清空一把
preparedStatement.clearBatch();
}
}
long end = System.currentTimeMillis();
System.out.println("添加结束 " + (end - start));
JDBCUtils.close(null, preparedStatement, connection);
}
批处理时一定要在 mysql.properties 配置文件中的 url 中加上 rewriteBatchedStatements=true