Java的Mysql使用
说明
通过Java的方式连接Mysql中的数据库,并对数据库中的数据进行增加 查询操作
使用Mysql所提供的第三方库中的类(Mysql的API) 对其进行操作
将Mysql Jar包添加到lib目录后,就可以使用其中的类对其Mysql数据库进行操作
Mysql Jar包的获取以及配置
然后jar包添加到库即可
使用步骤
Mysql Jar包中提供了很多类,如何去使用?
SUN公司将JDBC协议作为一个规范,提供给开发者, 规范的使用套路是什么?
① 加载驱动 Driver 类
原因: JDBC可以连接很多数据库,那么就需要告诉jdbc当前连接的是哪一个数据库,所以需要提供Driver类
② 创建连接对象 给定 URL、用户名、密码 等信息
③ 通过连接对象获取操作对象
④ 通过数据库操作对象,执行SQL语句获取执行结果
⑤ 如果是查询语句,那么需要对执行结果进行遍历操作
⑥ 将所有的连接及对象进行关闭操作
实例
package com.test.demo23;
import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo14Mysql {
public static void main(String[] args) throws SQLException {
// ① 加载驱动 Driver 类
/*
Interface Driver
每个驱动程序类必须实现的接口 -> Mysql来说也实现该接口
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
加载管理驱动
DriverManager 用于管理一组JDBC驱动程序的基本服务
可以通过
DriverManager.registerDriver 注册当前需要连接的Mysql驱动
*/
DriverManager.registerDriver(new Driver());
/*
② 创建连接对象 给定 URL、用户名、密码 等信息
DriverManager 中提供了静态方法 getConnection 获取Mysql连接
getConnection(String url, String user, String password)
url:
mysql的连接路径
IP安装mysql地址,有虚拟机看虚拟机IP
格式: jdbc:数据库类型://IP:port/数据库?设置参数1&设置参数1
jdbc:mysql://192.168.136.100:3306/stu
*/
Connection connection= DriverManager.getConnection("jdbc:mysql://192.168.118.100:3306/demo1?useSSL=false","root","123456");
/*
③ 通过连接对象获取操作对象
createStatement()
创建一个 Statement对象,用于将SQL语句发送到数据库。
*/
Statement statement = connection.createStatement();
/*
④ 通过数据库操作对象,执行SQL语句获取执行结果
*/
String sql = "INSERT INTO Course (Cid,Cname,Tid) VALUES (04,'物理',04)";
statement.executeUpdate(sql);
/*
⑥ 将所有的连接及对象进行关闭操作
*/
statement.close();
connection.close();
}
}
package com.test.demo23;
import com.mysql.jdbc.Driver;
import java.sql.*;
public class Demo14Mysql {
public static void main(String[] args) throws SQLException {
// ① 加载驱动 Driver 类
/*
Interface Driver
每个驱动程序类必须实现的接口 -> Mysql来说也实现该接口
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
加载管理驱动
DriverManager 用于管理一组JDBC驱动程序的基本服务
可以通过
DriverManager.registerDriver 注册当前需要连接的Mysql驱动
*/
DriverManager.registerDriver(new Driver());
/*
② 创建连接对象 给定 URL、用户名、密码 等信息
DriverManager 中提供了静态方法 getConnection 获取Mysql连接
getConnection(String url, String user, String password)
url:
mysql的连接路径
IP安装mysql地址,有虚拟机看虚拟机IP
格式: jdbc:数据库类型://IP:port/数据库?设置参数1&设置参数1
jdbc:mysql://192.168.136.100:3306/stu
*/
Connection connection= DriverManager.getConnection("jdbc:mysql://192.168.118.100:3306/demo1?useSSL=false","root","123456");
/*
③ 通过连接对象获取操作对象
createStatement()
创建一个 Statement对象,用于将SQL语句发送到数据库。
*/
Statement statement = connection.createStatement();
/*
④ 通过数据库操作对象,执行SQL语句获取执行结果
*/
String sql = "select * from Course ";
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
System.out.println(resultSet.getInt("Cid")
+ resultSet.getString("Cname") + resultSet.getInt("Tid"));
}
/*
⑥ 将所有的连接及对象进行关闭操作
*/
statement.close();
connection.close();
}
}
结果:
1语文2
2数学1
3英语3
4物理4
数据库样式
JDBC中重要的接口和类
DriverManager类(驱动管理类)里面全是静态方法,我们用它来注册驱动:
DriverManager 类中的静态方法 | 说明 |
---|---|
static void registerDriver(Driver driver) | 向 DriverManager 注册驱动程序 |
static Connection getConnection(String url, String user, String password) | 建立到给定数据库 URL 的连接 |
Statement接口(执行sql)用于执行静态 SQL 语句并返回它所生成结果的对象:
statement中的方法 | 说明 |
---|---|
int executeUpdate(String sql) | 执行更新语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,返回值是“影响数据库中的记录条数” |
ResultSet executeQuery(String sql) | 执行 SQL查询语句,该语句返回单个 ResultSet 对象 |
ResultSet接口(查询结果集),sql查询语句后可以将结果封装到ResultSet中:
ResultSet中的方法 | 说明 |
---|---|
boolean next() | 将光标从当前位置向前移一行。ResultSet 光标最初位于第一行之前;第一次调用 next 方法使第一行成为当前行;第二次调用使第二行成为当前行,依此类推(用来查询结果) |
String getString(int columnIndex) | 不管数据库中的数据类型是什么,都以String的形式取出(columnIndex是指取列数,第一列,第二列…) |
String getString(String columnLabel) | 不管数据库中的数据类型是什么,都以String的形式取出( columnLabel指查询语句中的列名) |
反射机制注册驱动(最常用的注册驱动方法)
加载和注册数据库驱动,数据库驱动由 mysql 厂商 "com.mysql.jdbc.Driver"提供
public static void main(String[] args) {
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false","root","root");
System.out.println(conn);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
基础操作
示例1:插入操作
import java.sql.*;
public class JDBCTest01 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
//1、注册驱动的第二种方法,告诉java我要连接mysql
Driver driver = new com.mysql.jdbc.Driver();
DriverManager.registerDriver(driver);
//2、获取连接,告诉java我要连接哪台机器的mysql,并写入用户和密码
//127.0.0.1和localhost都是本地ip地址
String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url,user,password);
System.out.println(conn);
//3、获取数据库操作对象(statement专门执行sql语句)
stmt = conn.createStatement();
//4、执行sql
String sql = "insert into dept(deptno,dname,loc) values(50,'军部','长安');";
//专门执行DML语句(insert、delete、update)
//返回值是“影响数据库中的记录条数”
int a = stmt.executeUpdate(sql);
System.out.println(a);
System.out.println(a == 1 ? "保存成功":"保存失败");
//5、处理查询结果集
//插入语句,暂时不需要查询
} catch (SQLException e) {
e.printStackTrace();
} finally {
//6、释放资源
//为了保证资源一定释放,在finally语句块中关闭资源
//分别要遵循从小到大依次关闭
if (stmt != null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
示例2:删除操作
import java.sql.*;
public class JDBCTest02 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
//1、注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//2、获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false","root","root");
//3、获取数据库操作对象
stmt = conn.createStatement();
//4、执行sql语句
String sql = "delete from dept where deptno = 50;";
int count = stmt.executeUpdate(sql);
System.out.println(count == 1 ? "删除成功":"删除失败");
} catch(SQLException e) {
e.printStackTrace();
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
示例3:从资源文件中读取连接数据库信息
将连接数据库的所有信息配置到配置文件jdbc.properties中:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useSSL=false
user=root
password=root
/*
JDBC工具类
*/
public class JDBCUtils {
//1.私有构造方法
private JDBCUtils(){};
//2.声明配置信息变量
private static String driverClass;
private static String url;
private static String username;
private static String password;
private static Connection conn;
//3.静态代码块中实现加载配置文件和注册驱动
static{
try{
//通过类加载器返回配置文件的字节流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");
//创建Properties集合,加载流对象的信息
Properties prop = new Properties();
prop.load(is);
//获取信息为变量赋值
driverClass = prop.getProperty("driverClass");
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");
//注册驱动
Class.forName(driverClass);
} catch (Exception e) {
e.printStackTrace();
}
}
//4.获取数据库连接的方法
public static Connection getConnection() {
try {
conn = DriverManager.getConnection(url,username,password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//5.释放资源的方法
public static void close(Connection conn, Statement stat, ResultSet rs) {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Connection conn, Statement stat) {
close(conn,stat,null);
}
}
实际开发中不建议把来连接数据库的信息写死到java程序中,因为用户可能不会把数据库的密码给你。
import java.sql.*;
import java.util.*;
public class JDBCTest04 {
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
String driver = bundle.getString("driver");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password = bundle.getString("password");
Connection conn = null;
Statement stmt = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url,user,password);
stmt = conn.createStatement();
int count = stmt.executeUpdate("insert into dept(deptno,dname,loc) values(50,'人事部','北京');");
System.out.println(count == 1? "保存成功":"保存失败");
} catch(SQLException e){
e.printStackTrace();
} catch(ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(conn != null) {
try {
conn.close();
} catch(SQLException e){
e.printStackTrace();
}
}
if(stmt != null) {
try {
stmt.close();
} catch(SQLException e){
e.printStackTrace();
}
}
}
}
}
示例4:处理查询结果集(遍历查询结果)
ResultSet接口中的next()
方法是用于遍历结果集的方法。它将指针从当前行移动到下一行,并检查是否有更多的数据可用。该方法返回一个布尔值,表示是否成功移动到下一行。
以下是关于next()
方法的一些重要信息:
next()
方法返回一个布尔值。如果存在下一行,则返回true
;否则,返回false
。- 第一次调用
next()
方法时,将指针移到结果集的第一行(如果有)。 - 每次调用
next()
方法后,指针将根据结果集中的数据移动到下一行。 - 如果
next()
方法返回true
,你可以使用其他方法(如getInt()
、getString()
等)来获取当前行的列值。 - 如果
next()
方法返回false
,表示已经到达结果集的末尾,没有更多的数据可用。
以下是一个示例代码片段,演示了如何使用next()
方法遍历结果集:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class ResultSetExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/database_name";
String username = "your_username";
String password = "your_password";
try {
Connection connection = DriverManager.getConnection(url, username, password);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM table_name");
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
// 处理当前行的数据
System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age);
}
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
释放资源时先释放查询结果集,再释放数据库操作对象,最后释放数据库连接对象。
sql注入现象
1、用户登录程序
在数据库中先建一个用户表:
create table t_user
(
id bigint auto_increment,
loginName varchar(255),
loginPwd varchar(255),
realName varchar(255),
primary key (id)
);
insert into t_user(loginName,loginPwd,realName) values('zhangsan','123','张三');
insert into t_user(loginName,loginPwd,realName) values('jack','123','杰克');
commit;
select * from t_user;
编写一个java程序,当输入的账户和密码与表中的数据一致时,显示“登录成功”,否则“登录失败”。
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.sql.*;
//模拟用户登录成功功能的实现
public class JDBCTest06 {
public static void main(String[] args) {
Map<String,String> userLoginInfo = initUI();
System.out.println(login(userLoginInfo) ? "登录成功" : "登录失败");
}
//传入一个map集合,并拿它与数据进行对比,如果账户密码合法就返回“true”,否则返回“false”
private static boolean login(Map<String, String> userLoginInfo) {
boolean flag = false;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false","root","root");
//3、获取数据库操作对象
stmt = conn.createStatement();
//4、执行sql语句
//String sql = "select .* from t_user where userName = '" + userLoginInfo.get("userName") + "' and userPassword = '" + userLoginInfo.get("' userPassword;");
String sql = "select * from t_user where loginName = '"+ userLoginInfo.get("userName")+ "' and loginPwd = '" + userLoginInfo.get("userPassword")+ "'";
rs = stmt.executeQuery(sql);
flag = rs.next();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return flag;
}
//输入函数,用户在此函数中输入自己的账户和密码,并存入map集合中去与数据库中的数据进行比较
private static Map<String,String> initUI() {
Scanner s = new Scanner(System.in);
System.out.printf("请输入账号: ");
String userName = s.nextLine();
System.out.printf("请输入密码: ");
String userPassword = s.nextLine();
Map<String,String> userLoginInfo = new HashMap<>();
userLoginInfo.put("userName",userName);
userLoginInfo.put("userPassword",userPassword);
return userLoginInfo;
}
}
执行结果:
2、演示sql注入现象
当我输入以下账户和密码时,它也显示登录成功!!
这种现象称为sql注入(黑客经常使用),这是一个安全隐患。
为什么会出现sql注入现象?
用户输入的信息中含有sql语句的关键字,并且这些关键字参与sql语句的编译过程。导致sql语句的原意被扭曲,进而达到sql注入。
因为我们上面的sql语句被写成了 select * from t_user where loginName = ‘lll’ and loginPwd = ‘lll’ or ‘1’ = ‘1’; 这个1=1是恒成立的。
3、解决sql注入
思想:不让用户的输入信息参加编译。 要解决 SQL 注入就不能让用户输入的密码和我们的 SQL 语句进行简单的字符串拼接。
方法:使用PreparedStatement接口
(1)prepareStatement()会先将 SQL 语句发送给数据库预编译。PreparedStatement 会引用着预编译后的结果。可以多次传入不同的参数给 PreparedStatement 对象并执行。减少 SQL 编译次数,提高效率。
(2)安全性更高,没有 SQL 注入的隐患。
操作请看注释,解释代码:
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class JDBCTest07 {
public static void main(String[] args) {
// 初始化界面
Map<String,String> userLoginInfo = initUI();
// 验证用户名和密码
boolean loginSuccess = login(userLoginInfo);
// 输出最后结果
System.out.println(loginSuccess ? "登录成功" : "登录失败");
}
/**
* 用户登录
* @param userLoginInfo 用户登录信息
* @return true表示登录成功,false表示登录失败
*/
private static boolean login(Map<String, String> userLoginInfo) {
boolean loginSuccess = false;
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2、获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false","root","root");
// 3、获取预编译的数据库操作对象
// sql语句的框架中,一个?,表示一个占位符,一个?将来接收一个值。注意:?不要用单引号括起来
String sql = "select * from t_user where loginName = ? and loginPwd = ?";
// 程序执行到此处,会发送sql语句框架给DBMS,DBMS对sql语句框架进行预编译。
ps = conn.prepareStatement(sql);
// 给占位符?传值,第一个?的下标是1,第二个?的下标是2(JDBC中下标都从1开始)
ps.setString(1,userLoginInfo.get("userName"));
ps.setString(2,userLoginInfo.get("userPassword"));
// 4、执行sql语句
rs = ps.executeQuery();
// 5、处理结果集
if(rs.next()) {
loginSuccess = true;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 6、释放资源
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return loginSuccess;
}
/**
* 初试化界面
* @return 用户输入的用户名和密码等登录信息
*/
private static Map<String, String> initUI() {
Scanner s = new Scanner(System.in);
System.out.print("请输入用户:");
String userName = s.nextLine();
System.out.print("请输入密码:");
String userPassword = s.nextLine();
Map<String,String> userLoginInfo = new HashMap<>();
userLoginInfo.put("userName",userName);
userLoginInfo.put("userPassword",userPassword);
return userLoginInfo;
}
}
三、JDBC事务
把注册驱动和获取连接封装到一个工具类中,以后就不用次次写代码都写那么多了:
import java.sql.*;
/*
JDBC工具类,简化JDBC编程
*/
public class DBUtil {
/**
* 工具类中的构造方法是私有的
* 因为工具类中的方法都是静态的,直接通过类名去调即可。
*/
private DBUtil(){}
/**
* 静态代码块,类加载的时候执行
* 把注册驱动程序的代码放在静态代码块中,避免多次获取连接对象时重复调用
*/
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase?useSSL=false","root","root");
}
public static void close(Connection conn, Statement ps, ResultSet rs){
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
在java中执行sql事务:
package ustc.java.jdbc;
import ustc.java.jdbc.DBUtil.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/*
行级锁/悲观锁
*/
public class JDBCTest14 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
// 开启事务
conn.setAutoCommit(false);
ps = conn.prepareStatement("select ename,job,sal from emp where job = ? for update ");
ps.setString(1,"MANAGER");
rs = ps.executeQuery();
while(rs.next()) {
System.out.println(rs.getString("ename") + "," + rs.getString("job") + "," + rs.getString("sal"));
}
// 提交事务(事务结束)
conn.commit();
} catch (SQLException throwables) {
// 回滚事务(事务结束)
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
} finally {
DBUtil.close(conn,ps,rs);
}
}
}
try {
conn = DBUtil.getConnection();
// 开启事务
conn.setAutoCommit(false);
ps = conn.prepareStatement("select ename,job,sal from emp where job = ? for update ");
ps.setString(1,"MANAGER");
rs = ps.executeQuery();
while(rs.next()) {
System.out.println(rs.getString("ename") + "," + rs.getString("job") + "," + rs.getString("sal"));
}
// 提交事务(事务结束)
conn.commit();
} catch (SQLException throwables) {
// 回滚事务(事务结束)
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
} finally {
DBUtil.close(conn,ps,rs);
}
}
}