javaWeb笔记

JAVAWEB知识点

——黄铭

1 JDBC

1.1 JDBC核心组件

DriverManager: 此类管理数据库驱动程序列表。使用通信协议将来自java应用程序的连接请求与适当的数据库驱动程序匹配。

Driver:此接口处理与数据库服务器的通信,我们很少会直接与Driver对象进行交互。而是使用DriverManager对象来管理这种类型的对象。

​ **Connection:**该接口具有用于连接数据库的所有方法。连接对象表示通信上下文,数据库的所有通信仅通过连接对象。

Statement:使用从此接口创建的对象将SQL语句提交到数据库。除了执行存储过程之外,一些派生接口还接受参数。

​ **ResultSet:**在使用Statement对象执行SQL查询后,这些对象保存从数据库检索的数据。它作为一个迭代器,允许我们移动其数据。

​ **SQLException:**此类处理数据库应用程序中发生的任何异常。

1.2 JDBC初始

  • **导入JDBC驱动包:**需要下载包含数据库编程所需的JDBC的jar包

  • 注册JDBC驱动程序: Class.forName(“com.mysql.jdbc.Driver”);

​ Driver myDriver = new com.mysql.jdbc.Driver();DriverManager.registerDriver( myDriver );

  • **创建连接:**需要使用*DriverManager.getConnection()*方法创建一个Connection对象,该对象表示与数据库的物理连接。

  • **执行查询:**需要使用类型为Statement的对象来构建和提交SQL语句到数据库。

  • **从结果集中提取数据:**需要使用相应的*ResultSet.getXXX()*方法从结果集中检索数据。

  • **释放资源:**需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集。

1.3 SQL语句执行

  • boolean execute(String SQL):如果可以检索到ResultSet对象,则返回一个布尔值true; 否则返回false。使用此方法执行SQL DDL语句或需要使用真正的动态SQL时。
  • int executeUpdate(String SQL):返回受SQL语句执行影响的行数。使用此方法执行预期会影响多个行的SQL语句,例如INSERT,UPDATE或DELETE语句。
  • ResultSet executeQuery(String SQL):返回一个ResultSet对象。当您希望获得结果集时,请使用此方法,就像使用SELECT语句一样。

1.4 案例演示

DML操作

public class JdbcDemo01 {
   
    public static void main(String[] args) throws Exception{
   
        ArrayList<Student> list = new ArrayList<>();
        Student student = null;

        // 驱动
        Class.forName("com.mysql.jdbc.Driver");

        // 连接
        String url = "jdbc:mysql://localhost:3306/gp";
        Connection conn = DriverManager.getConnection(url, "root", "1111");

        if (conn != null){
   
            System.out.println("连接成功!");
        }

        // 操作
        String sql = "select * from student";
        PreparedStatement preparedStatement = conn.prepareStatement(sql);

        // 结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()){
   
            int sno = resultSet.getInt("sno");
            String name = resultSet.getString("name");
            int age = resultSet.getInt("age");
            String gender = resultSet.getString("gender");
            Date birth = resultSet.getDate("birth");
            String adddress = resultSet.getString("address");
            student = new Student(sno,name,age,gender,birth,adddress);
            list.add(student);
        }

        // 关闭资源
        resultSet.close();
        preparedStatement.clearParameters();
        conn.close();

        // 打印
        for (Student student1 : list) {
   
            System.out.println(student1);
        }

    }
}

DQL操作

public class JdbcDemo02 {
   
    public static void main(String[] args) throws Exception {
   

        Class.forName("com.mysql.jdbc.Driver");

        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/gp", "root", "1111");

        Statement stat = conn.createStatement();


        //int insert = stat.executeUpdate("insert into student values(112,'xf',17,'女','1999-08-15','八百弓')",Statement.RETURN_GENERATED_KEYS);
        int delete = stat.executeUpdate("delete from student where sno = '112';");

//        ResultSet generatedKeys = stat.getGeneratedKeys();
//        if (generatedKeys.next()){
   
//            String sno = generatedKeys.getString(1);
//            System.out.println(sno);
//        }
        //System.out.println(insert);
        System.out.println(delete);

        stat.close();
        conn.close();
    }
}

1.5 SQL注入

​ 就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。

​ 使用statment的子类preparedStatment可以防止SQL注入,该对象采用预编译,其sql语句的每个?都是一个占位符,用来赋值。

public class JdbcDemo01 {
   
    public static void main(String[] args) throws Exception{
   

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = scanner.nextLine();
        System.out.println("请输入密码:");
        String password = scanner.nextLine();

        Class.forName("com.mysql.jdbc.Driver");

        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/gp", "root", "1111");

//        Statement stat = conn.createStatement();
//
//        ResultSet resultSet = stat.executeQuery("select * from user where username ='" + username + "' and password = '" + password + "';");

        PreparedStatement preparedStatement =  conn.prepareStatement("select * from user where username = ? and password = ?");
        preparedStatement.setString(1, username);
        preparedStatement.setString(2, password);

        ResultSet resultSet = preparedStatement.executeQuery();

        if (resultSet.next()){
   
            System.out.println("登录成功");
        }else {
   
            System.out.println("登陆失败");
        }
    }
}

1.6 三层架构

1.6.1 DAO(Date Access Object)

​ 此包中的类和接口的作用是,对数据库的表进行操作并返回结果。

1.6.2 service

​ 此包主要处理业务逻辑,即把DAO中得到的数据进行处理。也是开启事务的层,提交,回滚的层。

1.6.3 view

​ 此包是对进行了业务逻辑处理后的数据展示出来,

1.7 事务

​ 事务是一个原子操作,在同一个事务中,要么都执行成功,要么都执行失败。开启事务需要设置setAutoCommit(false)。并且在一个事务中需要连接同一个Connection,所以需要一个ThreadLocal类来绑定Connection。当一个失误中当升错误是,需要执行回滚操作。

 private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>(); 

//(2)获取连接
    public static Connection getConnection() {
   
        try {
   
            //1判断线程有没有连接,第一次执行一定是null
            Connection conn = threadLocal.get();
            if (conn == null) {
   

                conn = DriverManager.getConnection(url, user, password);
                //2绑定到线程
                threadLocal.set(conn);
                System.out.println("绑定了一个连接:" + conn.hashCode());
            }
            return conn;
        } catch (SQLException e) {
   
            e.printStackTrace();
        }
        return null;
    }

//与事务相关的四个方法
//1开启事务
public static void beginTransaction() throws SQLException {
   
    Connection connection = getConnection();
    if (connection != null) {
   
        connection.setAutoCommit(false);
    }
}

//2提交事务
public static void commit() throws SQLException {
   
    Connection connection = getConnection();
    if (connection != null) {
   
        connection.commit();
    }
}

//3回滚事务
public static void rollback() throws SQLException {
   
    Connection connection = getConnection();
    if (connection != null) {
   
        connection.rollback();
    }
}

//4关闭连接
public static void close() throws SQLException {
   
    Connection connection = getConnection();
    if (connection != null) {
   
        threadLocal.remove();//解除绑定
        connection.close();
        //System.out.println("close解除绑定,并关闭连接"+ connection.hashCode());
    }
}

1.8 优化DbUtils

​ 在DAO层中,对于增删改查有许多冗余代码,所以可以在DbUtils工具类中封装增删改,和查的方法。

1.8.1 增删改

public static int executeUpdate(String sql, Object... params) throws SQLException {
    //sql ?
    Connection conn = null;
    PreparedStatement pstat = null;
    try {
   
        conn = getConnection();
        pstat = conn.prepareStatement(sql);
        if (params != null) {
   
            for (int i = 0; i < params.length; i++) {
   
                pstat.setObject(i + 1, params[i]);
            }
        }
        return pstat.executeUpdate();
    } finally {
   
        closeAll(null, pstat, conn);
    }
}

1.8.2 通过RowMapper封装查询方法

RowMapper是一个借口,此接扣的方法是T getRow(Result rs)(),每一个实现类都是一个查询对象的操作。

public static <T> List<T> executeQuery(RowMapper rowMapper, String sql, Object... params) {
   
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;

    try {
   
        connection = getConnection();
        preparedStatement = connection.prepareStatement(sql);
        if (params != null) {
   
            for (int i = 0; i < params.length; i++) {
   
                preparedStatement.setObject(i + 1, params[i]);
            }
        }
        resultSet = preparedStatement.executeQuery();
        List<T> list = new ArrayList<>();
        while (resultSet.next()) {
   
            T t = (T) rowMapper.getRow(resultSet);
            list.add(t);
        }
    } catch (Exception e) {
   
        throw new BookException("查询失败", e);
    } finally {
   
        closeAll(resultSet, preparedStatement, connection);
    }
    return null;
}
public interface RowMapper<T> {
   

    T getRow(ResultSet rs);
}
public class BookRowMapper implements RowMapper<Book> {
   
    @Override
    public Book getRow(ResultSet rs) {
   
        try {
   
            int id = rs.getInt("id");
            String _title = rs.getString("title");
            String author = rs.getString("author");
            Date publicDate = rs.getTimestamp("publicDate");
            String publisher = rs.getString("publisher");
            String isbn = rs.getString("isbn");<
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值