大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。
Java学习之JDBC篇
0x00 前言
在一些web开发或者是数据存储的时候,肯定会使用到数据库来进行数据存储。 而在Java里面需要调用JDBC来对数据库进行操作。
0x01 JDBC概念
Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。
JDBC实现原理
代码语言:javascript复制Java通过java.sql.DriverManager来管理所有数据库的驱动注册,所以如果想要建立数据库连接需要先在java.sql.DriverManager中注册对应的驱动类,然后调用getConnection方法才能连接上数据库。
JDBC定义了一个叫java.sql.Driver的接口类负责实现对数据库的连接,所有的数据库驱动包都必须实现这个接口才能够完成数据库的连接操作。java.sql.DriverManager.getConnection(xx)其实就是间接的调用了java.sql.Driver类的connect方法实现数据库连接的。数据库连接成功后会返回一个叫做java.sql.Connection的数据库连接对象,一切对数据库的查询操作都将依赖于这个Connection对象。
0x02 JDBC使用
DriverManager驱动管理对象功能
注册驱动:
代码语言:javascript复制static void registerDriver(Driver driver) :
注册与给定的驱动程序 DriverManager 。
代码:
代码语言:javascript复制Class.forName("com.mysql.jdbc.Driver");
获取数据库连接:
代码语言:javascript复制static Connection getConnection(String url, String user, String password)
代码:
代码语言:javascript复制Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1/sql","root","root");
Connection数据库连接对象
获取执行sql 的对象
代码语言:javascript复制Statement createStatement()
PreparedStatement prepareStatement(String sql)
代码:
代码语言:javascript复制Statement statement = conn.createStatement();
Statement执行sql的对象
代码语言:javascript复制1. boolean execute(String sql) :可以执行任意的sql 了解
2. int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
*返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
3. ResultSet executeQuery(String sql) :执行DQL(select)语句
这里来写一段完整的代码,让我们的程序操作数据库,更新数据。
代码语言:javascript复制 public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/sql", "root", "root");
String sql = "update users set password = 500 where id =1";
Statement statement = connection.createStatement();
int i = statement.executeUpdate(sql);
System.out.println(i);
}
执行完成,再次打开我们的数据库可以发现数据已经更改了。
或者我们也可以把值定义在变量里面
代码语言:javascript复制 public static void main(String[] args) throws Exception {
String mycon = "jdbc:mysql://127.0.0.1:3306/sql";
String user = "root";
String password = "root";
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(mycon, user,password);
String sql = "update users set password = 500 where id =1";
Statement statement = connection.createStatement();
int i = statement.executeUpdate(sql);
System.out.println(i);
}
查询遍历表里内容
代码:
代码语言:javascript复制public class JdbcDemo1 {
public static void main(String[] args) throws Exception {
String mycon = "jdbc:mysql://127.0.0.1:3306/sql";
String user = "root";
String password = "root";
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(mycon, user,password); //建立连接
String sql = "select * from users "; //定义sql语句
Statement statement = connection.createStatement(); //创建执行sql对象
ResultSet resultSet = statement.executeQuery(sql); //执行sql语句
while (resultSet.next()){ //使用next让游标向下移动一行,判断是否为空
int id = resultSet.getInt(1); //获取查询id的值,从1开始索引
String name = resultSet.getString("username"); //获取查询的username字段内容
String passwd = resultSet.getString("password"); // //获取查询的password字段
System.out.println(id name passwd);
}
}
}
集合存储数据
mian:
代码语言:javascript复制package com.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class Jdbc {
public static void main(String[] args) throws Exception {
List<Test> list = new Jdbc().findAll();
System.out.println(list);
}
public List<Test> findAll() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/sql", "root", "root");
String sql = "select * from users";
Statement statement = conn.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
List<Test> list = new ArrayList<Test>();
Test test = null;
while (resultSet.next()){
int id = resultSet.getInt(1);
String username = resultSet.getString("username");
String password = resultSet.getString("password");
test = new Test();
test.setId(id);
test.setUsername(username);
test.setPassword(password);
list.add(test);
}
return list;
}
}
Test类:
代码语言:javascript复制package com.Test;
import java.util.Date;
public class Test {
private int id ;
private String username;
private String password;
public int getId() {
return id;
}
@Override
public String toString() {
return "Test{"
"id=" id
", username='" username '''
", password='" password '''
'}';
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
这里的代码虽然说使用起来方便,但是在我们后面修改账户或者是密码又或者是操作其他数据库的时候,我们就得修改代码,那么我们可以把这些连接信息配置到properties文件里面,后面需要的话修改文件就行了。
代码:
getconnection:
代码语言:javascript复制package util;
import java.io.FileReader;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
static {
try {
Properties pro = new Properties(); //创建Properties对象加载配置文件
ClassLoader classLoader = JDBCUtils.class.getClassLoader(); //获取class加载器
// System.out.println(classLoader);
URL res = classLoader.getResource("jdbc.properties");//获取文件资源
// System.out.println(res);
String path = res.getPath(); //获取文件路径
pro.load(new FileReader(path)); //加载文件
url = pro.getProperty("url"); //获取配置文件url 赋值给url
user = pro.getProperty("user");//获取配置文件url 赋值给user
password = pro.getProperty("password");//获取配置文件url 赋值给password
driver = pro.getProperty("driver");//获取配置文件url 赋值给dirver
Class.forName(driver);//driver加载到内存
}catch (Exception e){
System.out.println(e);}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
public static void close(Statement stmt,Connection conn){
if( stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if( conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet rs,Statement stmt, Connection conn){
if( rs != null){
try {
rs.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();
}
}
}
}
这里使用静态代码块来进行设置,静态代码块在创建对象时只会调用一次。
main方法代码:
代码语言:javascript复制package com.Test;
import util.JDBCUtils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class Jdbc {
public static void main(String[] args) throws Exception {
List<Test> list = new Jdbc().findAll();
System.out.println(list);
}
public List<Test> findAll() throws Exception {
// Class.forName("com.mysql.jdbc.Driver");
// Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/sql", "root", "root");
Connection conn = JDBCUtils.getConnection();
String sql = "select * from users";
Statement statement = conn.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
List<Test> list = new ArrayList<Test>();
Test test = null;
while (resultSet.next()){
int id = resultSet.getInt(1);
String username = resultSet.getString("username");
String password = resultSet.getString("password");
test = new Test();
test.setId(id);
test.setUsername(username);
test.setPassword(password);
list.add(test);
JDBCUtils.close(statement,conn); //关闭statement和conn
}
return list;
}
}
其他地方基本不变,只是在连接数据库和关闭数据库的时候,修改了一下代码。
这里注意几个坑,
1.properties文件必须放在src文件目录下,否则加载不出来
2.使用静态代码块的时候,如果要对方法进行传递参数,可以定义一个成员变量,然后对其进行传入,不能再去重新new一个变量。
这里来写个登录的小案例,依然用上面的代码来写。
代码语言:javascript复制package com.Test;
import util.JDBCUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class Login {
public static void main(String[] args) {
System.out.println("请输入账户");
Scanner sc = new Scanner(System.in);
String inputusername = sc.nextLine();
System.out.println("请输入密码");
String inputpassword = sc.nextLine();
boolean login = new Login().login(inputusername, inputpassword);
if (login){
System.out.println("登录成功");
}else {
System.out.println("用户名或者密码错误");
}
}
public boolean login(String username, String password){
Connection conn =null;
Statement statement =null;
ResultSet resultSet =null;
if (username== null||password==null){
return false;
}
try {
conn = JDBCUtils.getConnection();
String sql = "select * from users where username = '" username "' and password = '" password "' ";
System.out.println(sql);
statement= conn.createStatement();
resultSet = statement.executeQuery(sql);
return resultSet.next();
} catch (Exception e) {
System.out.println(e);
}finally {
JDBCUtils.close(resultSet,statement,conn);
}
return false;
}
}
这里来查询数据库第一条数据,输入账户密码,是否登录成功。
这里会发现我们直接就用了引号给拼接上去这样的代码很容易产生sql注入。
使用PreparedStatement进行预编译
代码语言:javascript复制package com.Test;
import util.JDBCUtils;
import java.sql.*;
import java.util.Scanner;
public class Login {
public static void main(String[] args) {
System.out.println("请输入账户");
Scanner sc = new Scanner(System.in);
String inputusername = sc.nextLine();
System.out.println("请输入密码");
String inputpassword = sc.nextLine();
boolean login = new Login().login(inputusername, inputpassword);
if (login){
System.out.println("登录成功");
}else {
System.out.println("用户名或者密码错误");
}
}
public boolean login(String username, String password){
Connection conn =null;
Statement statement =null;
ResultSet resultSet =null;
if (username== null||password==null){
return false;
}
try {
conn = JDBCUtils.getConnection();
String sql = "select * from users where username = ? and password = ?";
PreparedStatement pstmt = conn.prepareStatement(sql); //使用预编译传入sql语句
pstmt.setString(1,username); //设置第一个参数为username
pstmt.setString(2,password); //设置第二个参数为password
pstmt.executeQuery();
return resultSet.next();
} catch (Exception e) {
System.out.println(e);
}finally {
JDBCUtils.close(resultSet,statement,conn);
}
return false;
}
}
0x03 结尾
前面调试代码的时候,遇到了几个坑。调试了差不多一个小时,才才发现,原来是properties的位置放错了,导致获取不到包的资源,获取不到路径,直接抛出了一个异常。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/119944.html原文链接:https://javaforall.cn