JDBC-PreparedStatement以及对代码的封装

PreparedStatement:之后编写代码都会使用PreparedStatement代替Statement,原因是因为Statement中需要自己拼接sql语句而PreparedStatement不需要自己拼接。
代码封装:在之前所写的代码中会发现存在许多重复的代码,这样就会影响程序的效应,为了优化,我们需要将公共的部分封装起来,达到使用时直接调用即可。

一、PreparedStatement接口

Statement:

作用:发送SQL语句,通知数据库执行并得到结果
缺点:
	1、SQL语句拼接容易出错
	2、可读性差
	3、SQL攻击或者SQL注入  系统安全问题

PreparedStatement:

优点:
	1、带预编译的功能,让数据库开启预编译
	2、sql语句中的值使用?占位可读性更高
	3、使用?占位不需要拼接SQL,SQL攻击/SQL注入失败
提供的方法:
	1setXxx(int index,) 给指定位置的?赋值,XXX可以是string/int/Object
	2、执行增删改查的方法
	int excuteUpdate() 增删改,不需要传sql
	ResultSet executeQuery() 查询,不需要传sql
	

代码步骤:

1、创建PreparedStatement对象 pre
2、将SQL语句需要拼接的内容改为?
3、通过connection创建PreparedStatement,里面传入SQL变量进行预编译
4、使用PreparedStatement提供的setXxx(int index,值)给?赋值,index从1开始
(一般使用setXxx()方法,都会自动添加''不需要手动添加引号)
5、提供了增删改查的方法
int executeUpdate()
ResultSet executeQuery() 

对于Statement而言,存在安全问题,所以java提供了另一个接口PreparedStatement,该接口是Statement的子类,功能更加的强大,所以以后都会使用PreparedStatement替代Statement


 

二、代码封装

1、创建一个后缀名为properties的全局配置文件,将数据库的地址、用户名、密码等公共部分写入,该文件放在src目录下

# 驱动类
driverClass=com.mysql.jdbc.Driver
# 数据库url
url=jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=utf8&useSSL=false
# 用户名
username=root
# 密码
password=123456

 
2、创建一个pojo的包,该包专门放置对应表的类,例如操作的是tb_user表即可在该pojo包下创建对应的User类,将表中的字段名在类中使用private创建,并提供get和set方法以及toString方法,如果手动定义了构造函数还需要再自行添加一个无参的构造函数,(这里使用tb_user表===对应类名为User)
在这里插入图片描述

package pojo;

public class User {
    private String sname;
    private Integer spwd;

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Integer getSpwd() {
        return spwd;
    }

    public void setSpwd(Integer spwd) {
        this.spwd = spwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "sname='" + sname + '\'' +
                ", spwd=" + spwd +
                '}';
    }
}

 
3、创建一个util包,该包主要存放工具类,如JDBCUtil,该类主要用于编写对数据库公共的增删改查的方法,需要创建静态的Properties对象读取全局配置文件,将建立连接、释放资源、创建PreparedStatement、增删改、查的方法放入该类中,注意:查询方法中返回的是list集合,需要将ResultSet拿到的结果集通过反射的作用将User类中私有的属性添加到list集合中,由于不确定存放的类型,所以需要使用到泛型

package util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class JDBCUtil {
    // 创建一个properties集合对象
    static Properties pops = new Properties();

    // 静态代码块,程序在运行之前就会执行
    static {
        // 需要使用相对路径  类加载器(输入流)只加载src目录下的资源将PropertiesDemo.java加载到内存中
        InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties");

        try {
            pops.load(in);
            // 1、加载驱动类
            Class.forName(pops.getProperty("driverClass"));
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }


    }

    //    todo 建立连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(pops.getProperty("url"), pops.getProperty("username"), pops.getProperty("password"));
    }

    //    todo 释放资源
    public static void close(PreparedStatement psmt, ResultSet rs, Connection conn) {
        try {
            //6、关闭资源
            if (psmt != null) {
                psmt.close();
            }
            if (rs != null) {
                rs.close();
            }

            if (conn != null) {
                conn.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    //    todo 公共的创建PreparedStatement方法
    public static PreparedStatement createPreparedStatement(Connection conn, String sql, Object... params) throws SQLException {
        conn = JDBCUtil.getConnection();
        PreparedStatement psmt = conn.prepareStatement(sql);
        // 给?赋值
        if (params != null && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                psmt.setObject(i + 1, params[i]);
            }
        }
        return psmt;
    }

    //    todo 增删改的方法
    public static int executeUpdate(String sql, Object...items) {
        Connection conn = null;
        PreparedStatement psmt = null;
        try {
            conn = JDBCUtil.getConnection();
            psmt = createPreparedStatement(conn, sql, items);
            return psmt.executeUpdate();

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return 0;
    }

    //    todo 查的方法
    public static <T> List<T> executeQuery(String sql, Class<T> clazz, Object... items) {
        Connection conn = null;
        PreparedStatement psmt = null;
        ResultSet rs = null;


        try {
            // 获取连接
            conn = JDBCUtil.getConnection();
            // 创建prepareStatement
            psmt = createPreparedStatement(conn, sql, items);

            // 获取结果集
            rs = psmt.executeQuery();

            // 将结果集中的数据一条一条的放入list集合中,需要使用到反射,使用表对应创建的类的字节码文件并得到实例化对象最后获得字段(无论私有还是非私有)
            // 创建一个T类型的集合
            List<T> list = new ArrayList<>();
            // 遍历循环
            while (rs.next()) {
                // 1、获得实例化对象
                T t = clazz.newInstance();
                // 2、获取类中每个字段
                Field[] fields = clazz.getDeclaredFields();
                // 3、遍历字段
                for (Field field : fields) {
                    // 4、暴力反射
                    field.setAccessible(true);
                        /* 5、给属性赋值 底层调用 对象.属性 = 值
                        getObject(列索引)
                        getObject(列名)  约定: 属性名与列名一样,赋值
                         如果属性名与列名不一样: 列名:user_name username  属性名:username
                          给列名取一个属性名的别名*/
                    field.set(t, rs.getObject(field.getName()));
                }
                // 6、将fileds数组给list集合
                list.add(t);


            }
            return list;

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(psmt,rs,conn);
        }
        return null;

    }

}

 
4、创建一个dao包,该包主要存放对表进行操作的接口,将方法都写在该接口下即可

package Dao;

import pojo.Student;
import pojo.User;

import java.util.List;

/*todo User数据访问层
 *  对User的增删改查
 *  位于dao包下的都是接口
 *  Impl包下的是dao包接口的实现类
 * */
public interface StudentDao {
    /*
    * 根据id查询用户
    * */
    public Student queryBySname(Integer id);
    /*
    * 查询所有
    * */
    public List<Student> queryAll();
    /*
    * 插入User数据
    * */
    public int insert(Student s);
    /*
    * 根据sname删除
    * */
    public int deleteById(Integer id);
    /*
    * 修改用户,修改数据,一定不能修改主键
    * */
    public int update(Student s);
}

 
5、在dao包下创建一个Impl包,专门存放对应接口的实现类,下次增删改查就可以直接调用该实现类中的方法了。

package Dao.Impl;

import Dao.StudentDao;
import pojo.Student;
import util.JDBCUtil;

import java.util.List;

/*
 * todo 该类为StudentDao的实现类
 *
 * */
public class StudentDaoImpl implements StudentDao {

    @Override
    public Student queryBySname(Integer id) {
        String sql = "select * from   tb_student WHERE id = ?";
        List<Student> list = JDBCUtil.executeQuery(sql, Student.class, id);
        return list == null || list.isEmpty() ? null : list.get(0);
    }

    @Override
    public List<Student> queryAll() {
        String sql = "select * from tb_student";
        List<Student> students = JDBCUtil.executeQuery(sql, Student.class);
        return students;
    }

    @Override
    public int insert(Student s) {
        String sql = "inset into tb_student values(?,?,?,?)";
        return JDBCUtil.executeUpdate(sql, s.getId(), s.getName(), s.getSex(), s.getAge());

    }

    @Override
    public int deleteById(Integer id) {
        String sql = "delete from tb_student where id=?";
        return JDBCUtil.executeUpdate(sql,id);
    }

    @Override
    public int update(Student s) {
        return 0;
    }
}


 

三、目录结构

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用Druid连接池的Java代码示例: 1. 引入Druid的依赖库,可以在pom.xml中添加以下依赖: ``` <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> ``` 2. 在配置文件中添加Druid连接池的相关配置,比如application.properties: ``` # 数据库连接配置 spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver # Druid连接池配置 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.initialSize=5 spring.datasource.minIdle=5 spring.datasource.maxActive=20 spring.datasource.maxWait=60000 spring.datasource.timeBetweenEvictionRunsMillis=60000 spring.datasource.minEvictableIdleTimeMillis=300000 spring.datasource.validationQuery=SELECT 1 FROM DUAL spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false spring.datasource.poolPreparedStatements=true spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 spring.datasource.filters=stat,wall,log4j spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 ``` 3. 在Java代码中使用Druid连接池,比如: ```java import com.alibaba.druid.pool.DruidDataSource; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DruidDemo { public static void main(String[] args) throws SQLException { // 创建Druid连接池 DruidDataSource dataSource = new DruidDataSource(); // 设置连接池属性 dataSource.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false"); dataSource.setUsername("root"); dataSource.setPassword("root"); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setInitialSize(5); dataSource.setMinIdle(5); dataSource.setMaxActive(20); dataSource.setMaxWait(60000); dataSource.setTimeBetweenEvictionRunsMillis(60000); dataSource.setMinEvictableIdleTimeMillis(300000); dataSource.setValidationQuery("SELECT 1 FROM DUAL"); dataSource.setTestWhileIdle(true); dataSource.setTestOnBorrow(false); dataSource.setTestOnReturn(false); dataSource.setPoolPreparedStatements(true); dataSource.setMaxPoolPreparedStatementPerConnectionSize(20); dataSource.setFilters("stat,wall,log4j"); dataSource.setConnectionProperties("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000"); // 获取连接对象 Connection conn = dataSource.getConnection(); // 执行SQL查询 PreparedStatement ps = conn.prepareStatement("SELECT * FROM user"); ResultSet rs = ps.executeQuery(); while (rs.next()) { System.out.println(rs.getString("name")); } // 关闭连接 rs.close(); ps.close(); conn.close(); } } ``` 以上代码示例中,首先创建了一个Druid连接池对象,并设置了连接池属性,然后通过dataSource.getConnection()方法获取一个连接对象,最后执行SQL查询并关闭连接。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值