一、了解JDBC

  1. JDBC是什么?
    Java DataBase Connectivity(Java语言连接数据库)
  2. JDBC的本质
    JDBC是SUN公司制定的一套接口(interface)
    java.sql.*(这个软件包下有很多接口)
    开始面向接口编程,面向抽象编程,不要面向具体编程。
  3. JDBC编程六步(需要背会)
  • 第一步:注册驱动(告诉Java程序,即将要连接的是哪个数据库)
  • 第二步:获取连接
  • 第三步:获取数据库操作对象(专门执行sql语句的对象)
  • 第四步:执行SQL语句(DQL DML)
  • 第五步:处理查询结果集
  • 第六步:释放资源

二、连接数据库、实现用户登录

2.1前期准备

  • 还需要导入一个数据库驱动包,mysql-connector-java-5.1.47.jar
  • url:包括协议、IP、PORT(端口)、资源名
  • mysql的url:jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=false
    • jdbc:mysql:// 协议
    • localhost IP地址
    • 3306 mysql数据库端口号
    • smbms 具体的数据库实例名
public class JdbcTest {
public static void main(String[] args) throws SQLException {
try {
//1、注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());//这是一种加载驱动方式
//这是另外一种加载驱动方式,我们从文件中读信息
FileInputStream file = new FileInputStream("db.properties");
//创建Map集合对象
Properties properties = new Properties();
//将文件信息以键值对的形式加载出来
properties.load(file); //还可以使用一个比较简便的
ResourceBundle bundle = ResourceBundle.getBundle("文件名");
String driver = bundle.getString("key"); //获取文件信息
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
//通过反射加载驱动
Class.forName(driver);
System.out.println(driver);
//2、获取连接
Connection connection = DriverManager.getConnection(url, username, password);
System.out.println(connection);
//3、获取执行sql的对象
Statement statement = connection.createStatement();
String sql = "select * from smbms_role";
//4、执行sql语句5、返回结果集
ResultSet resultSet = statement.executeQuery(sql);
resultSet.next();
System.out.println(resultSet.getInt("id"));
//6、释放资源
resultSet.close();
statement.close();
connection.close();
//关闭资源时,必须从小到大按顺序关闭,并且每个都要try--catch
} catch (Exception e) {
e.printStackTrace();
}
}
}
//多写几遍,多查看API文档,了解每个类具体干什么的,你就懂了,也就学会了。
  • 增删改用int executeUpdate(insert/delete/update)
  • 查询用ResulSet executeQurey(select)
  • 查询时用boolean result.next(),若当前有数据则返回true,若没有则false
  • JDBC的下标时从1开始,而不是0

2.2用户登录代码实现

public class LoginTest {
public static void main(String[] args) {
//1.获取用户登录信息
Map<String,String> userInfo = userInfo();
//2.验证用户密码是否正确
boolean loginResult = userLogin(userInfo);
System.out.println(loginResult?"登录成功" : "登录失败");
} //获取用户登录信息
public static Map<String,String> userInfo() {
Scanner scan = new Scanner(System.in);
System.out.println("输入用户名:");
String username = scan.next();
System.out.println("输入密码:");
String password = scan.next();
HashMap<String, String> user = new HashMap<>();
user.put("username",username);
user.put("password",password);
return user;
}
//jdbc
public static boolean userLogin(Map<String,String> userInfo) {
boolean falg = false;
Connection conn = null;
Statement statement = null;
ResultSet resultSet = null;
try {
String username = userInfo.get("username");
String password = userInfo.get("password");
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=false", "root", "200506lx");
//3.获取操作对象
statement = conn.createStatement();
//4.执行sql
//5.返回结果
String sql = "select * from smbms_user where userCode = '"+username+"'and userPassword = '"+password+"'";
resultSet = statement.executeQuery(sql);
if(resultSet.next()) {
falg = true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6.释放资源
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return falg;
}
}

三、sql注入问题

  • asd'or'1'='1
  • 解决SQL注入问题
    • 只要用户提供的信息不参与SQL语句的编译过程,问题就解决了
    • 即使用户提供的信息中含有SQL语句的关键字,但是没有参与编译,不起作用。
    • 要想用户信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement
    • PreparedStatement这个接口继承了java.sql.Statement
    • 属于预编译的数据库操作对象,预先对SQL语句的框架进行编译,然后再给SQL语句传值
public static boolean userLogin(Map<String,String> userInfo) {
boolean falg = false;
Connection conn = null;
PreparedStatement ps = null;//将Statement换成PreparedStatement
ResultSet resultSet = null;
try {
String username = userInfo.get("username");
String password = userInfo.get("password");
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=false", "root", "200506lx");
//3.获取操作对象
//一个?就是一个占位符,接受一个值
String sql = "select * from smbms_user where userCode = ? and userPassword = ?";
ps = conn.prepareStatement(sql);
ps.setString(1,username); //1代表第一个?,给他设置值username
ps.setString(2,password); //JDBC下标从1开始
//4.执行sql
//5.返回结果
resultSet = ps.executeQuery();
if(resultSet.next()) {
falg = true;
}
}
}
  • 这样我们就解决了SQL注入问题

四、对比Statement和PreparedStatement

  • Statement存在sql注入问题,PreparedStatement解决了sql注入问题
  • Statement是编译一次执行一次,PreparedStatement是编译一次,可执行n次,效率较高。
  • PreparedStatement会在编译阶段做类型检查
  • 但是也有Statement用的地方。

五、JDBC事务演示

  • JDBC中只要执行任意一条DML语句,就提交一次
  • 记住三行代码搞定
  • conn.setAutoCommit(false)//将自动提交机制修改为手动提交机制,开启事务
  • conn.commit();//提交事务
  • conn.rollback();//事务回滚

六、JDBC工具类的封装

public class DButil {
/*
工具类中的构造方法都是私有的
因为工具类中的代码都是静态的,不需要new对象,直接采用类名调用
*/
private DButil(){
}
private static final String driver;
private static final String url;
private static final String username;
private static final String password;
//静态代码块随着类的加载而加载,并且只加载一次
static {
ResourceBundle rb = ResourceBundle.getBundle("db.properties");
driver = rb.getString("driver");
url = rb.getString("url");
username = rb.getString("username");
password = rb.getString("password");
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} //获取数据库的连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
//数据库资源关闭
public static void closeResource(Connection conn, PreparedStatement ps, ResultSet rs) {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

七、结尾

  • 对于数据库的JDBC内容就总结这么多,若想深入学习等待后续更新,基础部分掌握这些足矣。如果有不足之处,希望大家多多包涵,多多支持。如果有不懂的地方可以直接私信问我,欢迎来访!
  • 我将会继续更新关于Java的学习知识,感兴趣的小伙伴可以关注一下。
  • 文章写得比较走心,用了很长时间,绝对是copy过来的!
  • 尊重每一位学习知识的人,同时也尊重每一位分享知识的人。
  • 你的点赞与关注,是我努力前行的无限动力。

Java之JDBC详谈(数据库)的更多相关文章

  1. Java 通过JDBC查询数据库表结构(字段名称,类型,长度等)

    Java 通过JDBC查询数据库表结构(字段名称,类型,长度等) 发布者:唛唛家的豆子   时间:2012-11-20 17:54:02   Java 通过JDBC查询数据库表结构(字段名称,类型,长 ...

  2. MySQL_(Java)使用JDBC向数据库中修改(update)数据

    MySQL_(Java)使用JDBC向数据库发起查询请求 传送门 MySQL_(Java)使用JDBC向数据库中插入(insert)数据 传送门 MySQL_(Java)使用JDBC向数据库中删除(d ...

  3. MySQL_(Java)使用JDBC向数据库中删除(delete)数据

    MySQL_(Java)使用JDBC向数据库发起查询请求 传送门 MySQL_(Java)使用JDBC向数据库中插入(insert)数据 传送门 MySQL_(Java)使用JDBC向数据库中删除(d ...

  4. MySQL_(Java)使用JDBC向数据库中插入(insert)数据

    MySQL_(Java)使用JDBC向数据库发起查询请求 传送门 MySQL_(Java)使用JDBC向数据库中插入(insert)数据 传送门 MySQL_(Java)使用JDBC向数据库中删除(d ...

  5. MySQL_(Java)使用JDBC向数据库发起查询请求

    MySQL_(Java)使用JDBC向数据库发起查询请求 传送门 MySQL_(Java)使用JDBC创建用户名和密码校验查询方法 传送门 MySQL_(Java)使用preparestatement ...

  6. Java之JDBC操作数据库

    DBC JDBC就是一套接口,真正执行的是jar包里得实现类,通过泛型对象来执行实现类里的方法. 步骤: ###1.导入驱动jar包到工程中 ###2.编写代码注册驱动,我们要让程序知道用的是哪个驱动 ...

  7. Java 项目JDBC 链接数据库中会出现的错误

    1.出现的地方 package com.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql ...

  8. Java Spring JDBC访问数据库

    一.首先采用org.springframework.jdbc.datasource.DriverManagerDataSource类进行实现 1.applicationContext.xml配置如下: ...

  9. Java基础-JDBC访问数据库

    基本步骤: 加载数据库驱动 建立连接 创建SQL语句 执行SQL语句 处理执行结果 释放资源 代码示例: import java.sql.Connection; import java.sql.Dri ...

随机推荐

  1. CSS自定义属性与前端页面的主题切换

    基于级联变量的CSS自定义属性,已经出来很多年了. 虽然有less.sass等预处理器大行其道,但是自定义属性也有它的特点和用处,诸如在js中读写.作用域设置等等,在处理UI主题切换等功能上也发挥着很 ...

  2. 报错----运行springboot项目出现:Type javax.xml.bind.JAXBContext not present

    目的:运行springboot项目出现:Type javax.xml.bind.JAXBContext not present 环境: 问题:运行springboot项目出现:Type javax.x ...

  3. ssh端口转发学习笔记

    ssh端口转发学习笔记 ssh命令参数介绍 -C 压缩数据传输 -f 将 ssh 转到后台运行,即认证之后,ssh 自动以后台运行.不在输出信息 -n 将 stdio 重定向到 /dev/null,与 ...

  4. SVPWM实现概述

    SVPWM是FOC的基础,其实现流程大致如下所示: 1. 判断合成矢量所在扇区 2. 计算相邻矢量作用时间 3. 计算各桥臂导通时间 4. 得到各相PWM占空比 5. 更新相应寄存器值  SVPWM目 ...

  5. ShellExecuteA加载exe文件指定工作目录找不到文件的问题

    使用ShellExecuteA调用exe文件时,指定工作目录需要注意 函数原型为: HINSTANCE ShellExecuteA( HWND hwnd, LPCTSTR lpOperation, L ...

  6. Servlet:浏览器下载文件时文件名为乱码问题

    1 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletExcep ...

  7. SpringBoot和SpringCloud的区别?

    SpringBoot专注于快速方便的开发单个个体微服务. SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来, 为各个微服务之间提供 ...

  8. final, finally, finalize的区别?

    final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承.内部类要访问局部变量,局部变量必须定义成final类型.finally是异常处理语句结构的一部分,表示总是执行.fin ...

  9. redis 如何做内存优化?

    1.缩减键值对象 缩减键(key)和值(value)的长度, key长度:如在设计键时,在完整描述业务情况下,键值越短越好. value长度:值对象缩减比较复杂,常见需求是把业务对象序列化成二进制数组 ...

  10. 线程的 sleep()方法和 yield()方法有什么区别?

    ① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会:yield()方法只会给相同优先级或更高优先级的线程以运行的机会: ② 线程执行 sleep()方法后 ...