- 四年前存稿
Java操作数据库基本原理
概述
全称Java Database Connectivity,Java的数据库连接,使用Java语言操作数据库,定义了操作所有关系型数据库规则(接口)
使用步骤
我的mysql是8版本的,使用jar包时必须使用8版本的,如果驱动jar包跟mysql版本不一样,执行时会报错。且要把注册驱动改为com.mysql.cj.jdbc.Driver,在url那边也要修改,在表名后面加?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8。不然也报错。同时,mysql5之后的驱动jar包可以省略注册驱动的步骤
但是以下步骤是基础,真正使用的时候不用Statement对象(作了解),而是使用PreparedStatement对象,参照后面使用PreparedStatement ,能防止SQL注入问题,安全性更高,效率也更高。
public static void main(String[] args) throws Exception {
//1.导入驱动jar包
//2.注册驱动,这里可以注释掉不需要。
Class.forName("com.mysql.cj.jdbc.Driver");
//3.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8","root","888888");
//4.定义一个sql语句
String sql = "update account set balance = 500 where id = 1";
//5.获取执行sql对象
Statement stmt = conn.createStatement();
//6.执行sql,返回影响行数
int count = stmt.executeUpdate(sql);
//7.打印结果
System.out.println(count);
//8.释放资源
stmt.close();
conn.close();
}
JDBC各个类详解
DriverManager - - 驱动管理对象
①注册驱动:告知程序该使用哪一个数据库驱动jar包
//2.注册驱动,mysql5之后驱动jar包可以省略注册驱动,即这里可以注释掉不需要
Class.forName("com.mysql.cj.jdbc.Driver");
②获取数据库连接:
static Connection getConnection(String url,String user,String password)
url — 指定的连接路径
语法 — jdbc:mysql://ip地址(域名):端口号/数据库名称
例如 —"jdbc:mysql://localhost:3306/db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8"
其中,若mysql连接的是本地的mysql服务器,并且mysql默认服务端口号是3306,则url可以简写为"jdbc:mysql:///db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8"
(即省略ip地址和端口号:jdbc:mysql:///数据库名称)
user — 用户名
passwor — 密码
//3.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8","root","888888");
Connection - - - 数据库连接对象
①获取执行的sql对象
②管理事务
setAutoCommit(boolean autoCommit) – 开启事务
commit() - - 提交事务
rollback() - - 回滚事务
Statement - - - 执行sql对象
①执行sql语句
int executeUpdate(String sql)
- - 执行DML(insert、update、delete)、DDL(create、alter、drop)
ResultSet executeQuery(String sql)
- - 执行DQL(select)语句
执行insert语句测试.java
public static void main(String[] args) {
Statement stmt = null;
Connection conn = null;
try{
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.定义sql
String sql = "insert into account values(null,'monkey',3000)";
//3.获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql:///db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8","root","888888");
//4.获取执行sql的对象 Statement
stmt = conn.createStatement();
//5.执行sql
int count = stmt.executeUpdate(sql);//影响行数,若是ddl语句,count返回0
//6.处理结果
System.out.println(count);
if (count > 0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
}catch (ClassNotFoundException e){
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}finally {
//7.释放资源
//释放顺序应该是先stmt再是conn,但是看看try语快里面的执行顺序,很容易造成空指针异常
if (stmt != null){
try{
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (conn != null){
try{
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
ResultSet查询指定的数据.java
public static void main(String[] args) {
Statement stmt = null;
Connection conn = null;
ResultSet res = null;
try{
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.定义sql
String sql = "select * from account";
//3.获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql:///db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8","root","888888");
//4.获取执行sql的对象 Statement
stmt = conn.createStatement();
//5.执行sql
res = stmt.executeQuery(sql);//影响行数,若是ddl语句,count返回0
//6.处理结果
while (res.next()){
int id = res.getInt(1);
String name = res.getString("name");
double balance = res.getDouble(3);
System.out.println(id);
System.out.println(name);
System.out.println(balance);
}
/* 打印第二行数据,默认数据游标最初指向第一行的列名行
res.next();
int id = res.getInt(1);
String name = res.getString("name");
double balance = res.getDouble(3);
System.out.println(id);
System.out.println(name);
System.out.println(balance);*/
}catch (ClassNotFoundException e){
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//7.释放资源
//释放顺序应该是先stmt再是conn,但是看看try语快里面的执行顺序,很容易造成空指针异常
if (res != null){
try{
res.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (stmt != null){
try{
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (conn != null){
try{
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
ResultSet - - - 结果集对象,封装查询结果
boolean next()
- - 向下移动一行,判断是否有数据(末尾行),true为有,false没有
getXxx([可选参数])
- - 获取数据(Xxx代表数据类型),如int getInt()、String getString();可选参数int型代表列数编号如getString(1),可选参数String代表列名名称,getDouble(“price”)
/*
循环读取表中的数据
游标默认初始执向列名的一行,使用next()方法时向下移动一次
如果有数据返回true,没有返回false
类似于迭代器
*/
while(rs.next()){
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
}
PreparedStatement - - - 预编译执行sql对象,提高安全性
SQL注入问题 - - 在拼接sql时,有一些特殊关键字参与字符串拼接,造成安全性问题
解决SQL注入问题 - - 使用PreparedStatement对象解决
预编译的SQL - -参数使用?作为占位符
eg:select * from user where username=? and password=?
使用步骤如下,效率更加高,且能防止SQL注入问题,怎么改参见下面登录案例的代码
1.导入驱动包
2.注册驱动
3.获取数据库连接对象 Connection
4.定义sql,eg: select * from user where username=? and password=?
5.获取sql语句对象,Connection.preparedStatement(String sql)
6.给占位符 ? 赋值:setXxx(参数1,参数2)
- - 参数1代表?的位置标号,从1开始,参数2代表?的值
7.执行sql,返回结果,不需要传递sql语句
8.处理结果
9.释放资源
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
//连接数据检验是否正确
try {
//1.获取数据库连接
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "select * from user where xxx1= ? and xxx2=?";
//3.获取执行sql的对象,预编译
pstmt = conn.prepareStatement(sql);
//4.给?赋值
pstmt.setString(1,xxx1);
pstmt.setString(2,xxx2);
//5.执行查询
rs = pstmt.executeQuery();//这里不需要传参
//6.处理结果
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.close(rs,pstmt,conn);
}
JDBCUtils工具类
抽取JDBC工具类JDBCUtils,因为每次都要写JDBC的步骤(看上面的代码,每次写都要捕捉异常,判断,代码重复太高),为了方便所以来抽取一个工具类,拿来公用
创建在src文件下的配置文件jdbc.properties
url = jdbc:mysql:///db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8
user = root
password = 888888
driver = com.mysql.cj.jdbc.Driver
JDBCUtils.java
import java.io.FileReader;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
/*
JDBC工具类
*/
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
//静态代码块,只会执行一次
static {
//读取资源,获取值
//1.创建Properties集合类
Properties pro = new Properties();
try {
//2.加载文件
pro.load(new FileReader("src/jdbc.properties"));
//3.获取数据,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4.注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
/**
* 释放资源
* @param rs
* @param stmt
* @param coon
*/
public static void close(ResultSet rs,Statement stmt, Connection coon){
if (rs != null){
try{
rs.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (stmt != null){
try{
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (coon != null){
try{
coon.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
/*
重写函数,参数个数不同
*/
public static void close(Statement stmt, Connection coon){
if (stmt != null){
try{
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (coon != null){
try{
coon.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
实例 - - 登录
1.通过键盘录入用户名和密码
2.判断用户是否登录成功
使用到的JDBCUtils类参照上面工具类代码,配置文件根据自己情况修改
代码.java
public class jdbcDemo7 {
/**
* 登录函数
*/
public boolean login(String username,String password){
if (username == null && password == null){
return false;
}
Connection conn = null;
PreparedStatement pstmt = null;
//Statement stmt = null;
ResultSet rs = null;
//连接数据检验是否正确
try {
//1.获取数据库连接
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "select * from user where username= ? and password=?";
//3.获取执行sql的对象,预编译
pstmt = conn.prepareStatement(sql);
// stmt = conn.createStatement();
//4.给?赋值
pstmt.setString(1,username);
pstmt.setString(2,password);
//5.执行查询
rs = pstmt.executeQuery();//这里不需要传参
// rs = stmt.executeQuery(sql);
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.close(rs,pstmt,conn);
}
return false;
}
/*
测试
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入用户名:");
String username = sc.nextLine();
System.out.print("请输入密码:");
String password = sc.next();
// boolean flag = login(username,password);//直接调用静态方法static
boolean flag = new jdbcDemo7().login(username,password);//非静态方法用这种方式访问
if(flag){
System.out.println("登录成功");
}else{
System.out.println("用户名或密码错误");
}
}
}