1、JDBC 概述我们用大学的四年去怀念高中的三年,但是我们会用大学以后的余生去怀念大学的四年。
JDBC(Java Database Connectivity),Java数据库连接。sun公司为Java设计了一套 *** 作数据库的API(位于java.sql和javax.sql包下),然后每个数据库厂商提供实现JDBC接口的驱动。这样我们有了对应数据库的驱动,就能通过Java来 *** 作数据库啦。
2、开发环境搭建
(1)创建一个普通的Maven项目
(2) 导入mysql驱动
maven仓库地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.46
mysql mysql-connector-java5.1.46
(3)查看mysql驱动是否导入成功
(4)测试
public class MyTest { public static void main(String[] args) { try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); System.out.println("mysql数据库驱动加载成功!"); } catch (ClassNotFoundException e) { System.out.println("mysql数据库驱动加载失败!"); e.printStackTrace(); } } }
JDBC访问数据库步骤:
- 注册驱动(Driver)获取连接(Connection)获取数据库 *** 作对象(Statement)执行SQL语句处理查询结果集释放资源
注册数据库驱动
数据库驱动类 com.mysql.jdbc.Driver,实现了java.sql.Driver接口;查看源码后发现也是通过DriverManager.registerDriver()来注册驱动的,这样我们可以通过反射的方式来加载这个数据库驱动类Class.forName(xxx.Driver);
获取数据库的连接
url,统一资源定位符(网络中某个资源的绝对地址)。
URL由哪几个部分组成:协议,ip,port,资源名。
比如我们访问百度的主页:
http://39.156.66.18:80/index.html http:// 通信协议 39.156.66.18 服务器ip地址 80 端口,80是Web服务的默认端口 index.html 是服务器上某个资源名
mysql5.7和8.0驱动中url:
//mysql5.7, userSSL=false:关闭安全连接 useUnicode=true&characterEncoding=utf-8:字符集编码 url=jdbc:mysql://127.0.0.1:3306/mydatabase?useSSL=false&useUnicode=true&characterEncoding=utf-8 //mysql8.0,需要增加时区的配置:serverTimezone=GMT%2B8 url=jdbc:mysql://127.0.0.1:3306/mydatabase?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
示例代码:
import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; public class JDBCTest01 { public static void main(String[] args) { try { //1、注册驱动 Driver driver = new com.mysql.jdbc.Driver(); // 多态:父类引用指向子类对象 DriverManager.registerDriver(driver); //2、获取连接 String url = "jdbc:mysql://localhost:3306/mysqlstudy?useSSL=false&useUnicode=true&characterEncoding=utf-8"; String user = "root"; String password = "123456"; Connection connection = DriverManager.getConnection(url, user, password); System.out.println("数据库连接对象=" + connection); //com.mysql.jdbc.JDBC4Connection@3d646c37 } catch (SQLException e) { // 打印异常信息 e.printStackTrace(); } } }
3.2、执行SQL&释放资源
获取执行SQL的对象
SQL:
# 创建数据库 create database if not exists jdbctest character set utf8; # 使用数据库 use jdbctest ; # 创建数据表 CREATE TABLE IF NOT EXISTS `student` ( `id` INT ( 4 ) NOT NULL AUTO_INCREMENT COMMENT '学号', `name` VARCHAR ( 30 ) NOT NULL DEFAULT '匿名' COMMENT '学号', `pwd` VARCHAR ( 20 ) NOT NULL DEFAULT '123456' COMMENT '密码', `address` VARCHAR ( 100 ) DEFAULT NULL COMMENT '家庭地址', `email` VARCHAR ( 50 ) DEFAULT NULL COMMENT '邮箱', PRIMARY KEY ( `id` ) -- 把id设置主键 ) ENGINE = INNODB DEFAULT CHARSET = utf8;-- 设置引擎和字符编码
执行SQL
示例:
import java.sql.*; // 添加一条数据 public class JDBCTest01 { public static void main(String[] args) { Connection connection = null; Statement statement = null; try { //1、注册驱动 Driver driver = new com.mysql.jdbc.Driver(); // 多态:父类引用指向子类对象 DriverManager.registerDriver(driver); //2、获取连接 String url = "jdbc:mysql://localhost:3306/jdbctest?useSSL=false&useUnicode=true&characterEncoding=utf-8"; String user = "root"; String password = "123456"; connection = DriverManager.getConnection(url, user, password); System.out.println("数据库连接对象 = " + connection); //com.mysql.jdbc.JDBC4Connection@3d646c37 //3、获取数据库 *** 作对象 statement = connection.createStatement(); //4、执行sql String sql = "insert into student(name,pwd,address,email) values('pear','pear','新疆','[email protected]')"; //专门执行DML语句(insert、update、delete),返回值是影响数据库中的记录条数 int count = statement.executeUpdate(sql); System.out.println(count > 0 ? "添加成功!!!" : "添加失败!!!"); } catch (SQLException e) { // 打印异常信息 e.printStackTrace(); } finally { //5、释放资源 (从小到大依次关闭) try { if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } } }
如果你的控制台出现乱码,尝试这个方法点我。
ok已经将这条数据成功插入到数据表中啦!
3.3、JDBC删除&更新 *** 作
删除 *** 作
// 删除一条数据 public class JDBCTest02 { public static void main(String[] args) { Connection connection = null; Statement statement = null; try { //1、注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //2、获取连接 String url = "jdbc:mysql://localhost:3306/jdbctest?useSSL=false&useUnicode=true&characterEncoding=utf-8"; String user = "root"; String pwd = "123456"; connection = DriverManager.getConnection(url, user, pwd); System.out.println("Connection = " + connection); //3、获取数据库 *** 作对象 statement = connection.createStatement(); //4、执行SQL String sql = "delete from student where id = 10 "; int count = statement.executeUpdate(sql); //打印输出结果 System.out.println(count > 0 ? "delete success" : "delete falied"); } catch (SQLException e) { e.printStackTrace(); } finally { //5、释放资源 try { if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }
更新 *** 作
// 更新表中的数据 public class JDBCTest02 { public static void main(String[] args) { Connection connection = null; Statement statement = null; try { //1、注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //2、获取连接 String url = "jdbc:mysql://localhost:3306/jdbctest?useSSL=false&useUnicode=true&characterEncoding=utf8"; String user = "root"; String pwd = "123456"; connection = DriverManager.getConnection(url, user, pwd); System.out.println("Connection = " + connection); //3、获取数据库 *** 作对象 statement = connection.createStatement(); //4、执行SQL String sql = "update student set name='玉兔',address='月球' where name='joker'"; int count = statement.executeUpdate(sql); //打印输出结果 System.out.println(count > 0 ? "update success" : "update falied"); } catch (SQLException e) { e.printStackTrace(); } finally { //5、释放资源 try { if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } } }
成功修改表中的数据!
3.4、通过反射注册数据库驱动
public class MyTest { public static void main(String[] args) { try { // 注册驱动 Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
3.5、读取配置文件中的内容
在项目的资源目录resources中创建一个db.properties文件。
将我们的数据库配置信息写在db.properties中,目的是方便维护。
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbctest?useSSL=false&useUniCode=true&characterEncoding=utf-8 user=root password=123456
通过测试类来读取db.properties中的内容。
public class JDBCTest03 { public static void main(String[] args) { try { // 创建配置文件对象 Properties properties = new Properties(); // 通过类加载器获取配置文件db.properties的输入流 InputStream is = ClassLoader.getSystemResourceAsStream("db.properties"); // 将这个资源加载到配置文件对象中 properties.load(is); // 关闭输入流 is.close(); // 通过key获取配置文件对应的value String driver = properties.getProperty("driver"); String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); // 输出获取的内容 System.out.println("driver = " + driver); System.out.println("url = " + url); System.out.println("user = " + user); System.out.println("password = " + password); } catch (IOException e) { e.printStackTrace(); } } }4、实现用户登录功能
需求分析:
接收用户输入的用户名和密码;验证用户名和密码;返回给用户提示信息;
SQL语句:
use jdbctest; create table user ( id int not null auto_increment, name varchar(255) not null, password varchar(255) not null, vocation varchar(255), primary key (id) )engine= INNODB default charset= utf8; insert into user(`name`,`password`,`vocation`) values('白豆五','123456','大三'),('wangwu','wangwu','画家'),('zhangsan','7777','程序员');
db.properties:
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbctest?useSSL=false&useUniCode=true&characterEncoding=utf-8 user=root password=123456
示例代码:
import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Scanner; public class JDBCTest04 { public static void main(String[] args) { // 初始化界面 MapuserLoginInfo = initUI(); // 验证用户名和密码 boolean loginSuccess = login(userLoginInfo); // 打印提示信息 System.out.println(loginSuccess ? "success" : "fail"); } private static boolean login(Map userLoginInfo) { Connection conn = null; Statement stmt = null; ResultSet rs = null; // 定义一个红绿灯标识用户登录和失败 boolean loginSuccess = false; try { // 创建配置类对象 Properties p = new Properties(); // 通过类加载器获取类路径下的db.properties这个资源 InputStream is = ClassLoader.getSystemResourceAsStream("db.properties"); //加载资源 p.load(is); // 关闭流 is.close(); // 通过属性获取内容 String driver = p.getProperty("driver"); String user = p.getProperty("user"); String url = p.getProperty("url"); String password = p.getProperty("password"); //System.out.println(driver); //System.out.println(user); //System.out.println(url); //System.out.println(password); // 1、注册驱动 Class.forName(driver); // 2、获取连接 conn = DriverManager.getConnection(url, user, password); //System.out.println("数据库连接对象 = " + conn); // 3、获取数据库 *** 作对象 stmt = conn.createStatement(); // 执行sql String sql = "select * from user where name ='" + userLoginInfo.get("name") + "' and password = '" + userLoginInfo.get("password") + "'"; rs = stmt.executeQuery(sql); // 处理结果集 while (rs.next()) { // 登陆成功 loginSuccess = true; } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException throwables) { throwables.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 释放资源 close(rs, stmt, conn); } return loginSuccess; } private static Map initUI() { Scanner sc = new Scanner(System.in); System.out.println("用户名:"); String name = sc.nextLine(); System.out.println("密码:"); String password = sc.nextLine(); Map userLoginInfo = new HashMap (); userLoginInfo.put("name", name); userLoginInfo.put("password", password); return userLoginInfo; } public static void close(ResultSet rs, Statement stmt, Connection conn) { try { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } if (conn != null) { conn.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } }
5、SQL注入问题
通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
这次我们在上一个登录案例对密码做一些小手段,后面拼接一些字符串,竟然能登录成功。
分析:只要用户提供的信息不参与SQL语句的编译过程,问题就解决了。
解决方案:
可以利用正则表达式来防止用户输入一些非法字符,例如(‘=’,‘or’等)将statment换成PreparedStatement(预编译的数据库 *** 作对象);
PreparedStatement的原理:首先将SQL语句传入PreparedStatement中,然后把传入到SQL语句中的参数用?(占位符)来代替,然后该SQL语句会进行预编译,之后将获取的参数通过PreparedStatement中的set()方法传入编译后的SQL语句中,这样SQL语句就会先被编译再进行传值,这样就解决SQL注入问题。
示例代码:
import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Scanner; public class JDBCTest04 { public static void main(String[] args) { // 初始化界面 MapuserLoginInfo = initUI(); // 验证用户名和密码 boolean loginSuccess = login(userLoginInfo); // 打印提示信息 System.out.println(loginSuccess ? "登录成功" : "登录失败"); } private static boolean login(Map userLoginInfo) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; // 定义一个红绿灯标识用户登录和失败 boolean loginSuccess = false; try { // 创建配置类对象 Properties p = new Properties(); // 通过类加载器获取类路径下的db.properties这个资源 InputStream is = ClassLoader.getSystemResourceAsStream("db.properties"); //加载资源 p.load(is); // 关闭流 is.close(); // 通过属性获取内容 String driver = p.getProperty("driver"); String user = p.getProperty("user"); String url = p.getProperty("url"); String password = p.getProperty("password"); //System.out.println(driver); //System.out.println(user); //System.out.println(url); //System.out.println(password); // 1、注册驱动 Class.forName(driver); // 2、获取连接 conn = DriverManager.getConnection(url, user, password); //System.out.println("数据库连接对象 = " + conn); // 3、获取预编译的数据库 *** 作对象 String sql = "select * from user where name =? and password=?"; ps = conn.prepareStatement(sql); // 给占位符传值 ps.setString(1, userLoginInfo.get("user")); ps.setString(2, userLoginInfo.get("password")); // 4、执行sql rs = ps.executeQuery(); // 5、处理结果集 while (rs.next()) { // 登陆成功 loginSuccess = true; } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException throwables) { throwables.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 6、释放资源 close(rs, ps, conn); } return loginSuccess; } private static Map initUI() { Scanner sc = new Scanner(System.in); System.out.println("用户名:"); String name = sc.nextLine(); System.out.println("密码:"); String password = sc.nextLine(); Map userLoginInfo = new HashMap (); userLoginInfo.put("name", name); userLoginInfo.put("password", password); return userLoginInfo; } public static void close(ResultSet rs, Statement stmt, Connection conn) { try { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } if (conn != null) { conn.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)