java web入门jdbc连接数据库初学入门知识总结包括简单的防止sql注入和事务回滚

该文章适合初学java web 的朋友,看完了基本能够学会用jdbc操作数据库。

JDBC是什么:

java 数据库连接,java语言操作数据库

JDBC本质:

sun公司提供一个数据库连接的接口,各个数据库公司去实现该接口,并提供jar包(驱动)。我们利用这个接口编程,真正执行的是jar包中的实现类

JDBC连接数据库:

1.将驱动复制粘贴到工程文件目录中,如图
在这里插入图片描述
不一定非得是libs文件夹也可以叫别的名字。
jar包下载:MySQL8.0.26版本

jar包弄进去后,右键该驱动包点击add as library
在这里插入图片描述

连接数据库

这里要确保数据库已经连接好且数据库中有又来操作的表
代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JdbcDemo1p {
    public static void main(String[] args) throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.获取连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1","root","123456");
        //定义sql语句
        String sql = "INSERT INTO `db1`.`book`(`书名`, `ISBN`, `价格`, `版本`) VALUES('springboot实战', 'ISBN-9997', '97', '2021')";
        //获取执行对象
        Statement state = conn.createStatement();
        //执行sql
        int res = state.executeUpdate(sql);
        //打印结果,影响的行数
        System.out.println("影响了 "+res+" 行");
        //释放资源
        state.close();
        conn.close();
    }
}

运行结果:
在这里插入图片描述
说明:这里面的代码下文中会介绍,也可以自己查手册。这里涉及到很多重复代码,下文会把他们封装在一个工具类中。

到这里连接数据库并往数据库中插入一条数据就完成了。(上面暂时没有考虑空指针等问题)

将数据库连接放在一个工具类中

如果不放在工作类中,每次操作都需要来连接数据库,会产生很多重复的代码

连接数据库过程:
1.导入jar包(导入一次就行)
2.注册驱动
3.获取数据库连接对象
4.定义sql语句
5.获取执行sql语句的对象
6.处理结果
7.释放资源

除了6以外,其他的均装在一个类中(6也可以放进去只是,这里没有考虑)。像数据库账号密码和URL可以放在一个配置文件中。

类代码如下:

package util;

import javax.rmi.CORBA.Util;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {
    //驱动
    private static String driver;
    //连接对象
    private static String url;
    //账号
    private static String user;
    //密码
    private static String password;

    //不需要实例化对象,所以可以没有构造函数,但是代码需要写在静态代码块中调用


    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    static {
        //加载配置文件
        Properties pro = new Properties();
        //获取在src下的配置文件,可以写绝对路径(不容易出问题,但是不方便修改),也可以用ClassLoader加载
        ClassLoader classLoader = JDBCUtils.class.getClassLoader();
        URL url1 = ClassLoader.getSystemResource("jdbc.properties");
        String path = url1.getPath();
        //加载配置文件
        try {
            pro.load(new FileReader(path));
        } catch (IOException e) {
            e.printStackTrace();
        }

        //获取配置文件中的值
        driver = pro.getProperty("driver");
        url = pro.getProperty("url");
        user = pro.getProperty("user");
        password = pro.getProperty("password");

        //注册驱动
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


        try {
            DriverManager.getConnection(url,user,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        //
    }
    //连接对象,需要写在方法中返回连接对象
    public static Connection getConnection(String url,String user,String password) throws SQLException {
        return DriverManager.getConnection(url,user,password);
    }

    //释放资源
    public static void close(Connection conn, Statement state)  {
        if (null != conn){
            try{
                conn.close();
            } catch (Exception e){
            e.printStackTrace();
        }if (null != state){
                try{
                    state.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            }
    }

    //释放资源,重载
    public static void close(Connection conn, Statement state, ResultSet res){
        if (null != conn)
        try {
            conn.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        if (null != state){
            try{
                state.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        if (null != res){
            try{
                res.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

配置文件:

url=jdbc:mysql:///db1
user=root
password=123456
driver=com.mysql.jdbc.Driver

这样基本就可以用了
先演示一个不用工具类的:
代码:

import domain.Book;

import javax.swing.plaf.nimbus.State;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 *
 *将book表封装成对象,放在集合中
 */

public class JdbcDemo6 {
    public static void main(String[] args) throws Exception {
        List<Book> b = JdbcDemo6.findAll();
        for (Book b1:b){
            System.out.println(b1);
        }

    }

    public static List<Book> findAll() throws Exception {
        //注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //创建连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1","root","123456");
        //定义执行sql对象
        Statement state = conn.createStatement();
        //定义sql语句
        String sql = "SELECT * FROM `db1`.`book` LIMIT 0,1000";
        //执行sql语句
        ResultSet rs = state.executeQuery(sql);
        //处理结果
        rs.next();
        //定义存放数据的容器
        List<Book> books = new ArrayList<Book>();
        while (rs.next()){
            String bookName = rs.getString("书名");
            String bookISBN = rs.getString("ISBN");
            String bookPrice = rs.getString("价格");
            String bookVersion = rs.getString("版本");
            Book book = new Book();
            book.setBookName(bookName);
            book.setBookISBN(bookISBN);
            book.setBookPrice(bookPrice);
            book.setBookVersion(bookVersion);
            books.add(book);
        }
        //释放资源
        if(null !=rs ){
            rs.close();
        }
        if(null !=rs ){
            rs.close();
        }
        if(null !=rs ){
            rs.close();
        }
        return books;
    }
}


数据库表:
在这里插入图片描述

运行结果:
在这里插入图片描述

下面演示用了工具类的:
代码如下:

import domain.Book;
import util.JDBCUtils;

import javax.swing.plaf.nimbus.State;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 *
 * 用JDBCUtils工具类操作数据库查询book的信息
 */
public class JdbcDemo7 {
    public static void main(String[] args) throws Exception {
        //执行这个就已经连好数据库了
        Connection conn = JDBCUtils.getConnection();

        //定义sql执行对象
        Statement state = conn.createStatement();
        //定义sql
        String sql = "SELECT * FROM `db1`.`book` LIMIT 0,1000";

        //执行sql
        ResultSet rs = state.executeQuery(sql);

        //处理结果
        rs.next();
        while (rs.next()){
            String bookName = rs.getString("书名");
            String bookISBN = rs.getString("ISBN");
            String bookPrise = rs.getString("价格");
            String bookVersion = rs.getString("版本");
            Book b = new Book();
            b.setBookVersion(bookVersion);
            b.setBookPrice(bookPrise);
            b.setBookName(bookName);
            b.setBookISBN(bookISBN);
            System.out.println(b);
        }
    }
}

相对而言简化了一些,工具类代码和配置文件在上面
上面代码中漏写释放资源的代码了,可以参考上一段没用工具类的代码

执行结果(和上面没用工具类是一样的):
在这里插入图片描述

具体例子:实现登录

先创建用户表(这里没有考虑注册和加密问题):
在这里插入图片描述
代码:

import util.JDBCUtils;

import javax.swing.*;
import javax.xml.transform.Result;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * 实现用户登录
 */

public class JdbcDemo8 {
    public static void main(String[] args) throws Exception {
        //连接数据库
        Connection conn = JDBCUtils.getConnection();
        //定义sql执行对象
        Statement state = conn.createStatement();
        //定义sql
        String sql = "SELECT * FROM `db1`.`user` limit 0,1000";
        //执行sql
        ResultSet rs = state.executeQuery(sql);
        //处理结果
        Map<String,String> m = new HashMap();
        rs.next();
        //将密码保存到HashMap中,因为数据库里面只有一条数据,所以就没用循环
        String user = rs.getString("账号");
        String password = rs.getString("密码");
        m.put(user, password);

        //接受用户如输入的账号密码
        Scanner in1 = new Scanner(System.in);
        System.out.println("请输入账号:");
        String userInput = in1.next();

        Scanner in2 = new Scanner(System.in);
        System.out.println("请输入密码:");
        String passwordInput = in2.next();
        String checkPassword = new String();
        checkPassword = m.get(userInput);

        System.out.println("输入的账号"+userInput);
        if (checkPassword != null && checkPassword.equals(passwordInput)){
            System.out.println("登录成功");
        }else{
            System.out.println("用户名或者密码错误");
        }
        if (null !=conn){
            conn.close();
        }
        if (null !=state){
            state.close();
        }
        if (null != rs){
            rs.close();
        }

    }
}

运行结果:
在这里插入图片描述

JDBC事务操作(SQL注入,回滚)

SQL注入:静态sql语句如果被拼接就算是错误的输入也能登录
回滚:出现异常时,回到异常前的状态

执行修改前:
在这里插入图片描述
发生错误,事务回滚,:
此时虽然执行sql语句,但是没有提交事务,所以数据库中的数据不会发生改变
在这里插入图片描述
没有异常的正常情况:

import util.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class JdbcDemo10 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;

        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();
            //开启事务
            conn.setAutoCommit(false);

            //2.定义sql
            String sql1 = "update book set flag = flag + ? where flag = ?";
            //3.获取执行sql对象
            pstmt1 = conn.prepareStatement(sql1);
            //4. 设置参数
            pstmt1.setDouble(1,10);
            pstmt1.setInt(2,1);

            //5.执行sql
            pstmt1.executeUpdate();
            // 手动制造异常
//            int i = 3/0;

            //提交事务
            conn.commit();
        } catch (Exception e) {
            //事务回滚
            try {
                if(conn != null) {
                    conn.rollback();
                }
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            JDBCUtils.close(conn, pstmt1);
        }


    }
    }

执行结果:
没有发生异常所以没有输出
在这里插入图片描述
此时flag已经变成11,这是新加的字段,
在这里插入图片描述
注意:不管是否发生异常(是否回滚)都需要释放资源。

说明

个人学习笔记,如果错误感谢指出

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

漠上尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值