Java小白学点东西(18)

本文介绍了如何使用Java的JdbcUtil类封装JDBC操作,包括读取db.properties配置文件,实现连接数据库、预处理SQL(插入、删除、更新、查询)以防止SQL注入。此外,还讲解了JavaBean规范和BeanUtils工具类的使用,以及数据库元数据、参数元数据和结果集元数据的概念和应用。

1.重新封装JdbcUtil

1.在src下面新建一文件,这个文件叫db.properties,等一会儿,咱们这个文件需要在

JdbcUti这个类下面需要读取这个文件里面的内容

driver = com.mysql.jdbc.Driver        //数据库驱动Driver
url = jdbc:mysql://localhost:3306/javaqwz?useSSL=false        //我的url 连接的是mysql
user = root        //mysql用户名为root
password = 1234    //密码为1234
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

public class JdbcUtil {
    private static String driver;
    private static String url;
    private static String user;
    private static String password;
    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("./src/db.properties"));
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection() throws SQLException {
        Connection connection = DriverManager.getConnection(url,user,password);
        return connection;
    }
    public static void close(Connection connection) {
        close(connection, null, null);
    }
    //关闭两个资源 connection statement
    public static void close(Connection connection, Statement statement) {
        close(connection, statement, null);
    }
    //关闭三个资源的 connection  statement   resultSet
    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

2.预处理搬运工对象处理sql

咱们之前学过搬运工对象,搬运工对象的功能就是把sql语句搬运到数据库进行执行,

而且写的sql语句叫静态的sql语句。现在再学一种处理sql的方法,写动态的sql语句

这个叫预处理的搬运工。这个是咱们以后开发中用的,搬运工就不用了。

在写sql语句的时候,真实的sql语句使用到是‘?’代替真实的值。

数据的增加

import java.sql.*;

public class Test1 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        String sql = "insert into test1 values (?,?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1,"12");
        preparedStatement.setObject(2,"沙发上");
        preparedStatement.setObject(3,"45");
        int i = preparedStatement.executeUpdate();
        System.out.println(i);
    }
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

数据的​删除

import java.sql.*;

public class Test1 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        String sql = "delete from test1 where id = ?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1,"3");
        int i = preparedStatement.executeUpdate();
        System.out.println(i);
    }
}

 

数据的修改

import java.sql.*;

public class Test1 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        String sql = "update test1 set id=?,name=?,age=? where id=?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1,"99");
        preparedStatement.setObject(2,"马思唯");
        preparedStatement.setObject(3,"27");
        preparedStatement.setObject(4,"9");
        int i = preparedStatement.executeUpdate();
        System.out.println(i);
    }
}

 

 数据的查询

同样可以通过一个类来将数据库中的数据取出来后存入类对象集合中

首先咱们先创建一个类,其属性最好为数据库表中的字段名

public class Person {
    private int id;
    private String name;
    private int age;

    public Person(){}

    public Person(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

接着咱们开始操作,查找id为99的信息

import java.sql.*;
import java.util.ArrayList;

public class Test1 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        ArrayList<Person> people = new ArrayList<>();
        String sql = "select * from test1 where id = ?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1,"99");
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            int age = resultSet.getInt("age");
            people.add(new Person(id,name,age));
        }
        System.out.println(people);
        JdbcUtil.close(connection,preparedStatement);
    }
}

总结:

1.现在src文件夹下面创建一个lib文件夹,把mysql-connector-java-5.1.47.jar复制上去并导包
2.写一个db.properties这个文件到src这个下面
3.新建一个文件夹,下面写封装号的JdbcUtil这个类
4.直接写预处理搬运工就就可以了

3.使用预处理搬运工对象可以防止sql注入(了解即可)

sql注入就是一种不安全的情况,在删除数据或者查询数据的时候,sql语句的后面如果跟了or 1=1这个sql语句相当于操作了数据表所有数据

​
import com.qfedu.util.JdbcUtil;
​
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
​
public class Demo1 {
    public static void main(String[] args) throws SQLException {
        prepareTest();
    }
    //使用搬用工对象处理sql语句,有可能出现问题!!!!
    public static  void statementTest() throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        String id = "1 or 1=1";//这个是你的同事也就是竞争对手,用你的电脑,然后
        //修改了id这个字符串,就会将数据表中的数据全部删除掉了
        //delete from user1 where id = 1 or 1=1
        String sql = "delete from user1 where id = " + id;
        Statement statement = connection.createStatement();
        int i = statement.executeUpdate(sql);
        System.out.println(i);
        JdbcUtil.close(connection, statement);
    }
​
    //预处理的搬运工,可以防止sql注入
    public static void prepareTest() throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        String sql = "delete from user1 where id = ?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //preparedStatement.setObject(1, "5 or 1=1");
        preparedStatement.setObject(1, "5");
        int i = preparedStatement.executeUpdate();
        System.out.println(i);
        JdbcUtil.close(connection, preparedStatement);
    }
    /*
    * 为什么preparestatement可以防止sql注入?
    * 因为他的sql预。而且里面使用了占位符。规定了sql的结构!!!
    * 用户可以设置?的值,但是sql的结构不能再更改。如果想要在sql的后面加上
    * or 1=1就直接报错了
    *
    * */
}

4.JavaBean规范和BeanUtils工具类的使用【重点】

4.1JavaBean规范

JavaBean就是你写的一个实体类,

JavaBean规范:就是对类的一种规范写法。

1.私有化成员变量

2.一定要提供一个无参构造

3.一定要提供对应的setter和getter方法

4.每一个类作为一个单独的文件,并且使用public修饰

以后开发中可以利用JavaBean规范的额普适性完成一些操作!!!

一个表对应着一个类?为什么?而且表的字段和实体类属性对应好!!为什么要这样做!!!

咱们从数据库里面取出来数据,可以使用一个实体类进行接收赋值。

4.2BeanUtils类

Beanutils是基于反射,完成符合javabean规范的实体类的操作

查看官方的API,查不到?是因为Jdk压根就没有这个类,所以判定这个类第三方的类

所以需要导包才能使用这个类。

需要导包:common-beanutils-1.9.3.jar 导这一个包行吗?不行!!!

还需要依赖另外一个包 common-logging-1.1.3.jar

import com.qwzstu.test1.Person;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

public class Demo1 {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
        Person person = new Person();//创建一个person对象
        //给person对象的id、name、age属性复制
        BeanUtils.setProperty(person,"id",1);
        BeanUtils.setProperty(person,"name","张三");
        BeanUtils.setProperty(person,"age",21);
        //打印person对象可以看到赋值了
        System.out.println(person);
        //通过属性名获取值
        String name = BeanUtils.getProperty(person, "name");
        System.out.println(name);
        Person person1 = new Person();
        //复制
        BeanUtils.copyProperties(person1,person);
        System.out.println(person1);
        //克隆出一个新对象
        Object o = BeanUtils.cloneBean(person);
        System.out.println(o);
        //描述当前类的,结果是一个map集合
        Map<String, String> describe = BeanUtils.describe(person);
        Set<String> strings = describe.keySet();//返回键
        Collection<String> values = describe.values();//返回值
        System.out.println(strings);
        System.out.println(values);
    }
}

5.元数据【重要的点】

 

metaData

数据库元数据【不重要】:DatabaseMetaData

获取数据库连接对象信息

元数据包括有关数据库表,其支持的SQL语法,其存储过程,此连接的功能等的信息。

参数元数据【重要】:

结果集元数据【重要】:

5.1数据库元数据【DatabaseMetaData】

import com.qwzstu.test1.JdbcUtil;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;

public class Demo2 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        DatabaseMetaData metaData = connection.getMetaData();
        //获取驱动的名字
        String driverName = metaData.getDriverName();
        System.out.println(driverName);
        //获取url
        String url = metaData.getURL();
        System.out.println(url);
        //获取用户名
        String userName = metaData.getUserName();
        System.out.println(userName);
        //获取数据库产品名字
        String databaseProductName = metaData.getDatabaseProductName();
        System.out.println(databaseProductName);
    }
}

5.2参数元数据【重点】

 

ParameterMetaData

不是Connection对象获取出来的!!!

和数据库里面的sql语句有关 insert into person(name, age, info) values(?,?,?)

sql语句和预处理的搬运工有关系!!!

所以说咱们参数元数据对象是预处理的搬运工对象获取的

import com.qwzstu.test1.JdbcUtil;

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

public class Demo3 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        String sql = "insert into test1 values (?,?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ParameterMetaData parameterMetaData = preparedStatement.getParameterMetaData();
        //获取sql里面参数的个数
        int parameterCount = parameterMetaData.getParameterCount();
        System.out.println(parameterCount);
    }
}

5.3结果集元数据【重点】

ResultSetMetaData

只和查询出来结果有关

数据库元数据和Connection有关。

参数元数据和预处理的搬运工对象有关

结果集元数据和结果集有关

import java.sql.*;

public class Demo4 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement("select * from test1");
        ResultSet resultSet = preparedStatement.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        //获取字段的个数
        int columnCount = metaData.getColumnCount();
        System.out.println(columnCount);
        System.out.println("=====================");
        while (resultSet.next()){
            for (int i = 1; i <= columnCount; i++) {
                //metaData.getColumnName()是获取字段名,括号里是int类型数据意思是第几行的
                //System.out.println(metaData.getColumnName(i));

                //这个是通过遍历来进行打印出数据库的内容
                System.out.print(resultSet.getObject(metaData.getColumnName(i))+" ");
            }
            System.out.println();
        }
    }
}

 

 可以看到打印出来的结果和数据库中的一样,while循环控制的是一行一行往下走,for循环控制的是一列一列的遍历,最后出来的这个结果!

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

宇智波波奶茶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值