JDBC操作数据库

JDBC 实现Mysql数据库的CRUD操作

  1. 环境搭建
    在这里插入图片描述

  2. 获取数据库连接
    数据库配置文件:
    使用配置文件形式:db.properties

url = jdbc:mysql://127.0.0.1:3306/0107a?
user = root
password = 888

读取properties配置文件

public static Connection getconnection() throws Exception {
    //创建properties对象
    Properties properties = new Properties();
    //加载properties配置文件
    properties.load(new FileInputStream("src/db.properties"));
    //获取连接数据库的参数
    String url = properties.getProperty("url");
    String user = properties.getProperty("user");
    String password = properties.getProperty("password");
    //加载驱动
    Class.forName("com.mysql.jdbc.Driver");
    //获取链接
    Connection conn = DriverManager.getConnection(url, user, password);
    //返回链接
    return conn;
}

使用配置文件形式:Mysql.xml形式
这种情况下,xml的标签可自由定义

<?xml version="1.0" encoding="UTF-8"?>
<mysql>
    <url id="url">jdbc:mysql://127.0.0.1:3306/0107a?</url>
    <user id="user">root</user>
    <password id="pwd">888</password>
</mysql>
public static Connection getconnection() throws Exception {
        SAXReader sr = new SAXReader();
        //读取xml文件
        Document document = sr.read("src/mysql.xml");
        //获取xml文件根节点
        Element rootElement = document.getRootElement();
        System.out.println(rootElement.asXML());
        //获取根节点下所有子节点
        List<Element> elements = rootElement.elements();
        String url = null;
        String user = null;
        String password = null;
        for (Element element : elements) {
            if(element.getName().equals("url")){
                url = element.getText();
            }else if(element.getName().equals("user")){
                user = element.getText();
            }else if(element.getName().equals("password")){
                password = element.getText();
            }
        }
        System.out.println(url+" "+user+" "+password);

        //加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //获取链接
        Connection conn = DriverManager.getConnection(url, user, password);
        //返回链接
        return conn;
        }

两种方法均可获取mysql数据库的连接。

/**
 * 关闭资源的方法
 */
public static void closeResore(ResultSet rs, Statement st, Connection conn) throws SQLException {
    //关闭结果集
    if(rs !=null){
        rs.close();
    }
    //关闭语句体
    if(st != null){
        st.close();
    }
    //关闭连接
    if(conn != null){
        conn.close();
    }
}

在关闭资源的过程中注意一定的顺序,先开后关,不然会出错。

  1. 封装简单的JDBCUtils

```java
/**
 * 数据操作类
 */
public class JDBCUtils {
    //增删改
    public static int updateMethod(String sql, Object... args) throws Exception {
        //执行增删改后影响的行数
        int flag = 0;
        //创建链接
        Connection conn = null;
        PreparedStatement pst = null;
        //调用工具类获取链接
        conn = JDBCTool.getconnection();
        pst = conn.prepareStatement(sql);

        //如果有参数,通过遍历为sql语句的占位符赋值
        if(args != null){
            for (int i = 0; i < args.length; i++) {
                pst.setObject(i+1, args[i]);
            }
        }
        //执行sql语句
        flag = pst.executeUpdate();
        //关闭资源
        JDBCTool.closeResore(null, pst, conn);
        return flag;
    }

    /**
     * 执行查询语句
     */
    public static <T> List<T> selectMethod(Class<T> clazz, String sql, Object... args)    throws Exception {
        //初始化查询实体
        T entity = null;
        //初始化链接
        Connection connection = null;
        //初始化语句体
        PreparedStatement preparedStatement = null;
        //初始化结果集
        ResultSet resultSet = null;
        //创建链表,用于装学生对象
        List<T> list = new ArrayList<T>();
        //获取链接
        connection = JDBCTool.getconnection();
        //获取语句体
        preparedStatement = connection.prepareStatement(sql);
        //如果参数列表不为空,则通过循环为sql中的?占位符赋值
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
        }
        //执行语句体,并接收查询的结果集
        resultSet = preparedStatement.executeQuery();
        //获取表的元数据集合(表中列的名称构成的集合)
        ResultSetMetaData rsmd = resultSet.getMetaData();
        
        //遍历结果集
        while (resultSet.next()) {
        //创建实体类对象(student),用于接收查询到的数据,将数据封装到student中    //通过反射创建对象
            entity = clazz.newInstance();
            //遍历元数据集
            for (int i = 0; i < rsmd.getColumnCount(); i++) {
                //取出元数据集中的列名,并转换为string类型
                String columnLabel = rsmd.getColumnLabel(i + 1);
                //获取结果集的每列对应的值
                Object columnValue = resultSet.getObject(i + 1);
                //通过列名,获取实体类的成员变量列表
                Field field = clazz.getDeclaredField(columnLabel);
                //设置暴力访问
                field.setAccessible(true);
                //为实体类对象赋值
                field.set(entity, columnValue);
            }
            //将实体类对象放入到链表中
            list.add(entity);
        }
        //关闭资源
        JDBCTool.closeResore(resultSet, preparedStatement, connection);
        //返回list集合
        return list;
    }
}


4.	注意点。
PrepareStatement的用法
1.PreparedStatement是预编译(实例包含已编译的SQL语句)的,对于批量处理可以大大提高效率. 也叫JDBC存储过程
2.SQL语句可有一个IN或多个IN参数
---IN参数的值在SQL语句创建时未被指定,该语句为每一个IN参数保留一个问号(”?“)作为占位符
---每一个问号的值必须在该语句执行之前,通过适当的setInt或者setString方法提供。

与Statement的区别
1.Statement主要用于执行静态的SQL语句,内容固定不变。(对数据库只执行一次性存取)
2.PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。
3.PrepareStatement这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出它预编译的优越性。
4.除了缓冲的问题之外,使用PreparedStatement对象,那就是安全性(预防SQL注入攻击 )。
---传递给PreparedStatement对象的参数可以被强制进行类型转换,使开发人员可以确保在插入或查询数据时与底层的数据库格式匹配。

简单的sql注入攻击:
例如正常的delete语句 :delete from sysuser WHERE uid = '2' 

恶意delete语句 : delete from sysuser WHERE uid = ' 前端传入的值 '

前端传入的值为:2 ' OR 1 = 1 -- ;此时的SQL语句为  delete from sysuser WHERE uid = ' 2 ' OR 1 = 1 --  '

由于--单行注释的存在,--  '  被注释掉了;真正执行的SQL语句为 delete from sysuser WHERE uid = ' 2 ' OR 1 = 1,会将所有的数据库表中的数据全部删除
而使用预编译语句,最多最后写入数据库的值变为  2 ' OR 1 = 1 --ent对象的参数可以被强制进行类型转换,使开发人员可以确保在插入或查询数据时与底层的数据库格式匹配。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值