JDBC操作

任何一个一个程序员都离不开与数据库打交道,尤其是我们这些开发后台的.今天,小哥给大家整理了一些java中JDBC的操作管理方法;

主要有如下内容;

1,解决sql注入问题,并抽取工具类;实现增删改查;

a)sql注入

conn = DriverManager.getConnection(URL, NAME, PASSWORD);
//创建sql语句
String sql="select *from user where name='"+name+"'"+"password'";
//创建statement与数据库交互
st = conn.createStatement();
//执行sql语句并返回结果
rs = st.executeQuery(sql);
if(rs.next()){
System.out.println("操作成功");
}

由于字符串拼接组成的sql语句,导致statement在某些时候会出现问题;

比如在传入的那name和password中有关键字的情况;

1,当某人得知你的用户名时,无需知道密码即可直接登录网站,

如;我传入的用户名是:aaa ' or 1=1

或者用户名是aaa  -- (后面有一个空格)

这两种情况都会发生sql的注入问题.

解决办法是,使用preparedstatement采用占位符的方式解决;

package com.test03;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import com.pierce.domain.Person;

/**
 * 使用最初始的方法
 * 
 * @author Administrator
 *
 */
public class Test01 {
    /*
     * 准备数据库连接的工作
     */
    // 数据库地址;
    private static final String URL = "jdbc:mysql://localhost:3306/table";
    // 用户名:
    private static final String NAME = "root";
    // 密码;
    private static final String PASSWORD = "";
    // 驱动;
    private static final String DRIVE = "com.mysql.jdbc.Driver";

    // 程序加载时,加载驱动
    static {
        try {
            Class.forName(DRIVE);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 相数据库中插入一条信息;
    private static void insert(Person p) {
        // 创建连接
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = DriverManager.getConnection(URL, NAME, PASSWORD);
            // 创建sql语句
            String sql = "insert into person (name,age,description) values(?,?,?)";
            // 创建statement//解析sql语句
            ps = conn.prepareStatement(sql);
            //
            ps.setString(1, p.getName());
            ps.setInt(2, p.getAge());
            ps.setString(3, p.getDescription());
            // 对数据库进行操作;
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn = null;
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                ps = null;
            }
        }
    }

    public static void update(Person p) {
        Connection conn = null;
        PreparedStatement ps = null;
        // 获取连接
        try {
            conn = DriverManager.getConnection(URL, NAME, PASSWORD);
            // 创建一个sql语句
            String sql = "update person set name=?,age=?,description=? where id=?";
            // 获取statement用于与数据库交互操作;
            ps = conn.prepareStatement(sql);
            // 将数据存入到statement中;
            ps.setString(1, p.getName());
            ps.setInt(2, p.getAge());
            ps.setString(3, p.getDescription());
            ps.setInt(4, p.getId());
            // 执行sql语句
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                ps = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn = null;
            }
        }
    }

    public static void delete(int id) {
        Connection conn = null;
        PreparedStatement ps = null;
        // 创建连接;
        try {
            conn = DriverManager.getConnection(URL, NAME, PASSWORD);
            // 创建sql语句
            String sql = "delete from person where id=?";
            // 创建statement对象,与数据库进行交互;
            ps = conn.prepareStatement(sql);
            // 设置ps属性值
            ps.setInt(1, id);
            // 执行sql语句
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                ps = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn = null;
            }
        }
    }

    public static Person findById(int id) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        // 建立连接
        try {
            conn = DriverManager.getConnection(URL, NAME, PASSWORD);
            // 创建sql
            String sql = "select name,age,description from person where id=?";
            // 创建statement对象,与数据库交互
            ps = conn.prepareStatement(sql);
            // 设置ps的属性值
            ps.setInt(1, id);
            // 执行sql语句将数据返回到一个结果集
            rs = ps.executeQuery();
            // 创建一个person对象
            Person p = null;
            // 遍历结果集
            if (rs.next()) {
                p = new Person();
                p.setId(id);
                p.setName(rs.getString(1));
                p.setAge(rs.getInt(2));
                p.setDescription(rs.getString(3));
            }
            return p;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static List<Person> findAll() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        // 创建连接
        try {
            conn = DriverManager.getConnection(URL, NAME, PASSWORD);
            // 创建sql语句
            String sql = "select id,name,age,description from person";
            // 创建statement对象,实现与数据库的交互
            ps = conn.prepareStatement(sql);
            // 设置ps的属性值(略,直接执行sql语句即可)
            // 执行sql语句,返回一个结果集;
            rs = ps.executeQuery();
            // 创建一个lsit集合,用于存储数据
            List<Person> list = new ArrayList<Person>();
            Person p = null;
            // 遍历rs结果集
            while (rs.next()) {
                p = new Person();
                p.setId(rs.getInt(1));
                p.setName(rs.getString(2));
                p.setAge(rs.getInt(3));
                p.setDescription(rs.getString(4));
                list.add(p);
            }
            return list;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                rs = null;
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                ps = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn = null;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        // Person p=new Person(5,"张三",21,"风流倜傥");
        // insert(p);
        // update(p);
        // delete(10);
        // Person p = findById(7);
        // System.out.println(p);
        List<Person> persons = findAll();
        for (Person person : persons) {
            System.out.println(person);
        }
    }
}

上面呢,是使用了preparedstement的类,采用占位符的方式,其原理是,preparedstatement现将sql语句进行预编译,预编译之后,您传进来的东西都会作为一个字符串处理,就算里面有

关键字,也不会识别,这样就彻底解决了注入的问题;

我们发现,上面的代码重复的内容太多,并且,我们的数据库连接都是写死的,这样很不利于日后的项目维护;

所有,我接下来做两件事,:

1,抽取出一个工具类,将数据初始化工作,一并交给工具类;

工具类如下:

public class DBUtils {
    //私有化,不允许创建对象
    private DBUtils() {}
    //准备数据
    //数据库地址;
    private static final String URL;
    //用户名:
    private static final String NAME;
    //密码;
    private static final String PASSWORD;
    //驱动;
    private static final String DRIVE;
    //读取配置文件
    private static final ResourceBundle rb=ResourceBundle.getBundle("com.test03.db-config");
    
    //程序加载时,加载驱动,加载准备属性值
    static {
        DRIVE=rb.getString("driver");
        URL=rb.getString("url");
        NAME=rb.getString("name");
        PASSWORD=rb.getString("password");
        try {
            Class.forName(DRIVE);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //创建获取连接的工具
    public static Connection getConnection(){
        Connection conn=null;
        try {
            conn = DriverManager.getConnection(URL, NAME, PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
    
    //定义一个关闭资源的方法;
    public static void close(ResultSet rs,PreparedStatement ps, Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs=null;
        }
        if(ps!=null){
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            ps=null;
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn=null;
        }
    }
}

配置文件内容如下:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/table
name=root
password=

2)抽取出模版类:

public class JDBCTemplete {
    
    private JDBCTemplete() {}
    /**
     * 
     * @param sql
     * @param args
     * @return 
     */
    public static int update(String sql,Object...args){
        Connection conn=null;
        PreparedStatement ps = null;
        try {
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement(sql);
            if(args!=null){
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i+1, args[i]);
                }
            }
            return ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            return -1;
        }finally{
            DBUtils.close(null, ps, conn);
        }
    }
    
    public static Object query(String sql,ResultSetHandler handler,Object...args){
        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet rs=null;
        try {
            conn =DBUtils.getConnection();
            ps = conn.prepareStatement(sql);
            if(args!=null){
                for (int i = 0; i < args.length; i++) {
                    ps.setObject(i+1, args[i]);
                }
            }
            rs = ps.executeQuery();
            return handler.doHandler(rs);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            DBUtils.close(rs, ps, conn);
        }
        return null;
        
    }
}

这里的模版类涉及到了可变参数,至于可变参数的提取原理,我们下期在解释;

    public class PersonDaoImpl {
        
        //相数据库中插入一条信息;
        public void insert(Person p) {
            String sql="insert into person (name,age,description)values(?,?,?)";
            JDBCTemplete.update(sql, p.getName(),p.getAge(),p.getDescription());
        }
        public void update(Person p){
            String sql="update person set name=?,age=?,description=? where id=?";
            JDBCTemplete.update(sql,p.getName(),p.getAge(),p.getDescription(),p.getId());
        }
        
        public void delete(int id){
            String sql="delete from person where id=?";
            JDBCTemplete.update(sql, id);
        }
        
        public Person findById(final int id){
            String sql="select name,age,description from person where id=?";
            return (Person)JDBCTemplete.query(sql, new ResultSetHandler() {
                @Override
                public Object doHandler(ResultSet rs) throws SQLException {
                    Person p=null;
                    if(rs.next()){
                        p=new Person();
                        p.setId(id);
                        p.setName(rs.getString(1));
                        p.setAge(rs.getInt(2));
                        p.setDescription(rs.getString(3));
                    }
                    return p;
                }
            }, id);
        }
        
        @SuppressWarnings("unchecked")
        public List<Person> findAll(){
            String sql="select id,name,age,description from person";
            return (List<Person>)JDBCTemplete.query(sql, new ResultSetHandler() {
                @Override
                public Object doHandler(ResultSet rs) throws SQLException {
                    List<Person>list=new ArrayList<Person>();
                    Person p=null;
                    while(rs.next()){
                        p=new Person();
                        p.setId(rs.getInt(1));
                        p.setName(rs.getString(2));
                        p.setAge(rs.getInt(3));
                        p.setDescription(rs.getString(4));
                        list.add(p);
                    }
                    return list;
                }
            });
        }
    }

PersonDao的实现类,注意这里的查询方法中有一个结果集的接口,使用匿名对象,实现结果集的接收工作;

好了,今天先理到这,下一期,我会给大家介绍如下内容:

2,使用dbutils工具类和连接池技术(c3p0,druid),降低数据库访问过程中性能消耗问题;

3,介绍dbutils工具类中9大结果集处理器的使用;

4,介绍mysql中的事物管理.

猜你喜欢

转载自www.cnblogs.com/pierceming/p/8934895.html