Java连接MySQL数据库
什么是JDBC?
Java Database Connectivity(Java语言链接数据库)
JDBC的本质是什么?
JDBC是SUN公司定制的一套接口(interface)
接口都有调用者和实现者
面向接口调用、面向接口实现类,这都属于面向接口编程
JDBC编程六步
第一步:注册驱动(连接所选择的数据库)
第二步:获取连接(JVM的进程和数据库进程之间的通道打开)
第三步:获取数据库操作对象(专门执行sql语句的对象)
第四步:执行SQL语句(DQL、DML…)
第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这一步)
第六步:释放资源
注意:查询结果集的方法是 数据库对象.next() 判断将要查找的下一位是否存在,若存在就返回true,不存在就返回false,可以使用while循环判断。类似于指针,或迭代器。
第一种创建数据库对象的方法:Statement
代码实例:
这里用到了资源绑定器,方便修改数据库信息
jdbc.properties
这种方法可能会导致SQL注入
根本原因是?
用户输入的信息中含有sql语句的关键字,这些关键字参与sql语句的编译过程,
导致sql语句原意被扭曲
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/bjpowernode?serverTimezone=UTC
user=root
password=xxxxx
1234
import java.sql.*;
import java.util.ResourceBundle;
/*
实际开发中不建议把连接数据库的信息写死到java程序中。
*/
//查询结果集
public class JDBCTest {
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 connection=null;
Statement statement=null;
ResultSet resultSet=null;
try {
//1、注册驱动(常用方式)
Class.forName(driver);
//2、连接
connection= DriverManager.getConnection(url,user,password);
//3、创建数据库对象
statement=connection.createStatement();
//4、执行SQL语句(查询结果集)
String sql="select empno,ename,sal from emp";
//5、查询结果集
//专门执行DQL语句的语法,用executeQuery(),返回值ResultSet
resultSet=statement.executeQuery(sql);
while (resultSet.next()){
//取数据
//getString()方法的特点:不管数据库中数据类型是什么,都以String返回
String empno=resultSet.getString(1);//JDBC中所有下标从1开始
String ename=resultSet.getString(2);//第二列
String sal=resultSet.getString("sal");//第三列(可以写列名)
System.out.println(empno+","+ename+","+sal);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
//6、释放资源
} finally {
try {
//释放查询结果集
if(resultSet!=null)
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
//释放数据库操作对象
if(statement!=null)
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
//释放连接
if(connection!=null)
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
注意:
- 查询结果集执行DQL语句的语法,用executeQuery(),返回值类型ResultSet
- 增删改执行DML语句的语法,用executeUpdate(),返回值类型 int “影响数据库中的记录条数”
- 释放资源,遵循从小到大依次关闭,分别对其try…catch
第二种创建数据库对象的方法:PreparedStatement(常用)
这种方法解决SQL注入
只要用户提供的信息不参与SQL语句的编译过程,问题就解决了
使用java.sql.PreparedStatement
PreparedStatement接口继承了java.sql.Statement
PreparedStatement属于预编译的数据库对象
PreparedStatement的原理是:预先对SQL语句的框架进行编译,然后载个SQL语句传“值”
PreparedStatement效率高,编译一次,执行N次
例:
实现功能:
1、需求:
模拟用户登录功能的实现
2、业务描述:
程序运行的时候,提供一个输入的入口,可以让用户输入用户名和密码
用户输入用户名和密码之后,提交信息,java程序收集到用户信息
Java程序连接数据库验证用户名和密码是否合法
合法:显示登陆成功
不合法:登录失败
代码实例:
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class JDBCTest {
private static Object Collection;
private static Object Statement;
public static void main(String[] args) {
//初始化一个界面
Map<String, String> userLogin = chuShiHuaUI();
//验证用户名和密码
Boolean loginSuccess=Login(userLogin);
//输出结果
System.out.println(loginSuccess?"登录成功":"登录失败");
}
/**
* 用户登录
* @param userLogin 用户登录信息
* @return 返回true/false
*/
private static Boolean Login(Map<String, String> userLogin) {
//打标记
boolean flag=false;
//单独定义变量
String u=userLogin.get("loginname");
String p=userLogin.get("password");
//JDBC代码
Connection connection=null;
PreparedStatement pStatement=null;
ResultSet resultSet=null;
try {
//1、注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2、获取连接
connection= DriverManager.getConnection(
"jdbc:mysql://localhost:3306/bjpowernode?serverTimezone=UTC",
"root",
"XXXXX"
);
//3、创建数据库对象
//SQL语句框架 其中一个 ?表示一个占位符,一个 ?将来接收一个“值”
String sql="select * from t_user where loginname= ? and password= ? ";
pStatement=connection.prepareStatement(sql);
//给占位符 ?传值(第一个问号下标是1,第二个问号下标是2)
pStatement.setString(1,u);
pStatement.setString(2,p);
//4、执行sql
resultSet=pStatement.executeQuery();
//5、处理结果集
if(resultSet.next()){
flag=true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//6、释放资源
try {
if(resultSet!=null)
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(pStatement!=null)
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {if(connection!=null)
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return flag;
}
/**
* 初始化用户界面
* @return 用户输入的用户名和密码信息
*/
private static Map<String, String> chuShiHuaUI() {
Scanner s=new Scanner(System.in);
System.out.print("用户名:");
String username=s.nextLine();
System.out.print("密码:");
String password=s.nextLine();
Map<String,String> userLogin=new HashMap<>();
userLogin.put("loginname",username);
userLogin.put("password",password);
return userLogin;
}
}
JDBC中的事务
conn.setAutoCommit(false); 将自动提交机制改为手动提交
conn.commit(); 提交事务
conn.rollback(); 回滚事务
代码实例:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/*
JDBC中事务是自动提交的,若需要控制,则可以修改为手动提交事务
*/
public class JDBCTest08 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
try {
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.创建连接
conn= DriverManager.getConnection(
"jdbc:mysql://localhost:3306/bjpowernode?serverTimezone=UTC",
"root",
"xxxxx"
);
//将自动提交机制改为手动提交
conn.setAutoCommit(false);
//3.获取数据库操作对象
//4.执行SQL语句
String sql="update t_user set loginname=?,password=?,name=? where id=?";
ps=conn.prepareStatement(sql);
//给?传值
ps.setString(1,"zhangsan");
ps.setString(2,"123");
ps.setString(3,"ZHANGSAN");
ps.setString(4,"1");
int count = ps.executeUpdate();
System.out.println(count==1?"修改成功":"修改失败");
ps.setString(1,"lisi");
ps.setString(2,"456");
ps.setString(3,"LISI");
ps.setString(4,"2");
count += ps.executeUpdate();
System.out.println(count==2?"修改成功":"修改失败");
//提交事务
conn.commit();
} catch (Exception e) {
//回滚事务
if(conn!=null){
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
e.printStackTrace();
} finally {
//6.释放资源
if(ps!=null){
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
JDBC代码简化(创建工具类)
创建工具类
package util;
import java.sql.*;
/*
JDBC工具类,简化JDBC方法
*/
public class DBUtil {
/*
工具类中的构造方法都是私有的
因为工具类中的方法都是静态的,不需要NEW对象,直接采用类名调用
防止new对象
*/
private DBUtil(){ }
//静态代码块在类加载时执行,并且只执行一次
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接对象
* @return 返回连接对象
* @throws Exception
*/
public static Connection getConnection() throws Exception{
//获取连接
return DriverManager.getConnection(
"jdbc:mysql://localhost:3306/bjpowernode?serverTimezone=UTC",
"root",
"xxxxx"
);
}
/**
* 释放资源
* @param conn 连接对象
* @param ps 数据库操作对象
* @param rs 结果集
*/
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();
}
}
}
}
测试类
1.测试DBUtil
2.测试模糊查询
import util.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/*
1.测试DBUtil
2.模糊查询
*/
public class JDBCTest09 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
//获取连接(DBUtil类加载时就注册驱动了)
conn= DBUtil.getConnection();
//获取数据库操作对象
String sql="select ename from emp where ename like ?";
ps=conn.prepareStatement(sql);
ps.setString(1,"_A%");
rs=ps.executeQuery();
while (rs.next()){
System.out.println(rs.getString("ename"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放资源
DBUtil.close(conn,ps,rs);
}
}
}