zoukankan      html  css  js  c++  java
  • 简易 DBUtil 封装

                                                        

    Dao包结构图:

                                                 

    1.首先连接数据库

     1 package com.util.db;
     2 
     3 import java.sql.Connection;
     4 import java.sql.DriverManager;
     5 import java.sql.ResultSet;
     6 import java.sql.SQLException;
     7 import java.sql.Statement;
     8 import java.util.ResourceBundle;
     9 
    10 import javax.management.loading.PrivateClassLoader;
    11 
    12 import org.omg.CORBA.PRIVATE_MEMBER;
    13 
    14 /**
    15  * 连接数据库
    16  * @author Administrator
    17  *
    18  */
    19 public class DBConn {
    20 public static String URL;
    21 public static String USERNAME;
    22 public static String PASSWORD;
    23 public static String DRIVER;
    24 private static  ResourceBundle resourceBundle = ResourceBundle.getBundle("com.util.db.db_config");
    25 private DBConn() {}
    26 /**
    27  *为连接数据库变量赋值 
    28  *加载jdbc驱动
    29  */
    30 static{
    31     URL = resourceBundle.getString("jdbc.url");
    32     USERNAME = resourceBundle.getString("jdbc.username");
    33     PASSWORD = resourceBundle.getString("jdbc.password");
    34     DRIVER = resourceBundle.getString("jdbc.driver");
    35     try {
    36         Class.forName(DRIVER);
    37     } catch (ClassNotFoundException e) {
    38         e.printStackTrace();
    39     }
    40 }
    41 /**
    42  * 连接数据库,若连接失败则返回空
    43  * @return
    44  */
    45 public static Connection getConnection() {
    46     Connection conn = null;
    47     try {
    48         conn = DriverManager.getConnection(URL, USERNAME,PASSWORD);
    49         System.out.println("连接成功!");
    50     } catch (SQLException e) {
    51         e.printStackTrace();
    52         System.out.println("连接失败");
    53     }
    54     return conn;
    55 }
    56 /**
    57  * 关闭数据库连接
    58  * @param rs
    59  * @param st
    60  * @param conn
    61  */
    62 public static void close(ResultSet rs,Statement st,Connection conn){
    63     try {
    64         if (rs != null) {rs.close();}
    65         if (st != null) {st.close();}
    66         if (conn !=null) {conn.close();}
    67     } catch (SQLException e) {
    68         e.printStackTrace();
    69     }
    70     
    71 }
    72 public static void main(String[] args) {
    73     System.out.println(URL);
    74     System.out.println(USERNAME);
    75     System.out.println(PASSWORD);
    76     System.out.println(DRIVER);
    77     
    78 }
    79 }

    连接所需配置文件如下:

    jdbc.url = jdbc:mysql://localhost:3306/test?characterEncoding=utf8
    jdbc.username = root
    jdbc.password = 000000
    jdbc.driver =com.mysql.jdbc.Driver

    2.对增删该查基本操作做定义  使用不定参数 来解决增删改的参数不同

     1 package com.util.db;
     2 
     3 import java.sql.Connection;
     4 import java.sql.PreparedStatement;
     5 import java.sql.ResultSet;
     6 import java.sql.SQLException;
     7 
     8 /**
     9  * 为数据库操作提供方法模板
    10  * @author Administrator
    11  *
    12  */
    13 public class JdbcTemplete {
    14     /**
    15      * 更新操作
    16      * 返回 int 类型的操作行数 用作判断操作成功与否
    17      * 若操作异常  则返回 -1
    18      * @param sql
    19      * @param args
    20      * @return
    21      */
    22 public int update(String sql,Object...args){
    23     Connection conn = null;
    24     PreparedStatement ps =  null;
    25     conn = DBConn.getConnection();
    26     try {
    27         ps = conn.prepareStatement(sql);
    28         if(args!=null){
    29             for(int i = 0; i< args.length; i++){
    30             ps.setObject(i+1, args[i]);    
    31             }
    32         }
    33       
    34         int rs =  ps.executeUpdate();
    35         System.out.println("操作成功!");
    36         return rs;
    37     } catch (SQLException e) {
    38         e.printStackTrace();
    39 //        try {
    40 //            //事务回滚
    41 //            conn.rollback();
    42 //        } catch (SQLException e1) {e1.printStackTrace();}
    43         System.out.println("更新异常");
    44         return -1;
    45     }finally{
    46         DBConn.close(null, ps, conn);
    47     }    
    48 }
    49 /**
    50  *  查询操作 不做结果处理
    51  *  结果处理放在  ResultSetHandler 
    52  *  由调用时编写匿名类  采用策略模式  使用户采用不同策略 处理不同对象
    53  * @param sql
    54  * @param handler
    55  * @param args
    56  * @return
    57  */
    58 public Object query(String sql, ResultSetHandler handler, Object...args) {
    59     Connection conn = null;
    60     PreparedStatement ps = null;
    61     ResultSet rs = null;
    62     try {
    63         conn = DBConn.getConnection();
    64         ps = conn.prepareStatement(sql);
    65         if (args != null) {
    66             for (int i = 0; i < args.length; i++) {
    67                 ps.setObject(i+1, args[i]);
    68             }
    69         }
    70         rs = ps.executeQuery();
    71         return handler.doHandler(rs);
    72     } catch (SQLException e) {
    73         e.printStackTrace();
    74         return null;
    75     }finally{
    76         DBConn.close(rs, ps, conn);
    77     }
    78 }
    79 }

    3.对操作查询结果作出接口声明  使用策略模式  对于不同的javaBean有不同的处理

    package com.util.db;
    
    import java.sql.ResultSet;
    import java.sql.SQLException;
    /**
     * 操作连接数据库的结果集
     * 声明接口可以对具体的实体做不同处理
     * @author Administrator
     *
     */
    public interface ResultSetHandler {
    public Object doHandler(ResultSet rs) throws SQLException;
    }

    4.定义javaBean

     1 package com.domain;
     2 
     3 public class Person {
     4 private int id;
     5 private String name;
     6 private int age;
     7 private String description;
     8 public Person() {
     9     super();
    10 }
    11 public Person(String name, int age, String description) {
    12     super();
    13     this.name = name;
    14     this.age = age;
    15     this.description = description;
    16 }
    17 public Person(int id, String name, int age, String description) {
    18     super();
    19     this.id = id;
    20     this.name = name;
    21     this.age = age;
    22     this.description = description;
    23 }
    24 public int getId() {
    25     return id;
    26 }
    27 public void setId(int id) {
    28     this.id = id;
    29 }
    30 public String getName() {
    31     return name;
    32 }
    33 public void setName(String name) {
    34     this.name = name;
    35 }
    36 public int getAge() {
    37     return age;
    38 }
    39 public void setAge(int age) {
    40     this.age = age;
    41 }
    42 public String getDescription() {
    43     return description;
    44 }
    45 public void setDescription(String description) {
    46     this.description = description;
    47 }
    48 @Override
    49 public String toString() {
    50     return "Person [id=" + id + ", name=" + name + ", age=" + age
    51             + ", description=" + description + "]";
    52 }
    53 
    54 }

    5. 定义Dao  对具体操作  声明接口

     1 package com.dao;
     2 
     3 import java.sql.SQLException;
     4 import java.util.List;
     5 
     6 import com.domain.Person;
     7 
     8 /**
     9  * 用户功能接口
    10  * @author Administrator
    11  *
    12  */
    13 public interface PersonDao {
    14 public void add(Person person)throws SQLException;
    15 public void update(Person person)throws SQLException;
    16 public void delete (int id)throws SQLException;
    17 public Person findById(int id)throws SQLException;
    18 public List findAll()throws SQLException;
    19 
    20 
    21 } 

    6.对用户的操作进行实现

     1 package com.dao.impl;
     2 
     3 import java.sql.ResultSet;
     4 import java.sql.SQLException;
     5 import java.util.ArrayList;
     6 import java.util.List;
     7 
     8 import javax.management.j2ee.statistics.JDBCConnectionPoolStats;
     9 
    10 import com.dao.PersonDao;
    11 import com.domain.Person;
    12 import com.util.db.JdbcTemplete;
    13 import com.util.db.ResultSetHandler;
    14 
    15 public class PersonDaoImpl implements PersonDao {
    16 private JdbcTemplete jdbcTemplete;
    17 public PersonDaoImpl(){
    18     jdbcTemplete = new JdbcTemplete();
    19 }
    20     /**
    21      * 添加
    22      */
    23     @Override
    24     public void add(Person person) throws SQLException {
    25        String sql = "insert into person(name,age,description)value(?,?,?)";
    26        jdbcTemplete.update(sql, person.getName(),person.getAge(),person.getDescription());
    27     
    28     }
    29     /**
    30      * 更新操作
    31      */
    32     @Override
    33     public void update(Person person) throws SQLException {
    34            String sql ="update person set name=?,age=?,description=? where id=?";
    35            jdbcTemplete.update(sql, person.getName(),person.getAge(),person.getDescription(),person.getId());
    36     }
    37 
    38     @Override
    39     public void delete(int id) throws SQLException {
    40         String sql = "delete from person where id = ?";
    41         jdbcTemplete.update(sql,id);
    42     }
    43 
    44     @Override
    45     public Person findById(final int id) throws SQLException {
    46         String sql = "select name,age,description from person where id =?";
    47           return (Person) jdbcTemplete.query(sql, new ResultSetHandler() {
    48             @Override
    49             public Object doHandler(ResultSet rs) throws SQLException {
    50                 Person person = null;
    51                 if (rs.next()) {
    52                     person = new Person();
    53                     person.setId(rs.getInt(id));
    54                     person.setName(rs.getString(1));
    55                     person.setAge(rs.getInt(2));
    56                     person.setDescription(rs.getString(3));
    57                 }
    58                 return person;
    59             }
    60         },id );
    61     
    62     }
    63 
    64     @Override
    65     public List findAll() throws SQLException {
    66         String sql = "select id,name,age,description from person";
    67         return (List) jdbcTemplete.query(sql,new ResultSetHandler() {
    68             @Override
    69             public Object doHandler(ResultSet rs) throws SQLException {
    70                 List<Person> personList = new ArrayList<>();
    71                 Person person =null;
    72                 while (rs.next()) {
    73                     person = new Person();
    74                     person.setId(rs.getInt(1));
    75                     person.setName(rs.getString(2));
    76                     person.setAge(rs.getInt(3));
    77                     person.setDescription(rs.getString(4));
    78                     personList.add(person);
    79                 }
    80                 return personList;
    81             }
    82         });
    83         
    84     }
    85 
    86 }

    7.编写测试类

     1 package com.test;
     2 
     3 import java.sql.SQLException;
     4 import java.util.List;
     5 
     6 import com.dao.PersonDao;
     7 import com.dao.impl.PersonDaoImpl;
     8 import com.domain.Person;
     9 
    10 public class Test {
    11     /**
    12      * 
    13      * @param args
    14      */
    15 public static void main(String[] args) {
    16     PersonDao personDao = new PersonDaoImpl();
    17 
    18     try {
    19 
    20 //        personDao.add(new Person("CCC", 13, "CCC"));
    21         
    22         personDao.delete(3);
    23 //        
    24 //        personDao.update(new Person(3, "DDD", 10, "DDD"));
    25 //        
    26 //        
    27 //        Person p4 = personDao.findById(2);
    28 //        System.out.println(p4.toString());
    29 //        
    30 //        
    31 //        List<Person> personList = personDao.findAll();
    32 //        for (Person p : personList) {
    33 //            System.out.println(p.toString());
    34 //        }
    35         
    36     } catch (SQLException e) {
    37         e.printStackTrace();
    38     }
    39 }
    40 }
    1.Statement、PreparedStatement和CallableStatement都是接口(interface)。  
    2.Statement继承自Wrapper、PreparedStatement继承自Statement、CallableStatement继承自PreparedStatement。 
    3.  
     a.Statement:  
        普通的不带参的查询SQL;支持批量更新,批量删除;  
     b.PreparedStatement:  
        可变参数的SQL,支持占位符,每个占位符可占一个位,
         编译一次,执行多次,效率高;  
        安全性好,有效防止Sql注入等问题;  
        支持批量更新,批量删除;  
     c.CallableStatement:  
        继承自PreparedStatement,支持带参数的SQL操作;  
        支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持; 

    PreparedStatement是预编译的,使用PreparedStatement有几个好处  
    1. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。 
    2. 安全性好,有效防止Sql注入等问题。  
    3.  对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;  
    4.  代码的可读性和可维护性。

    如何防止注入攻击:

     如果你是做Java web应用开发的,那么必须熟悉那声名狼藉的SQL注入式攻击。去年Sony就遭受了SQL注入攻击,被盗用了一些Sony play station(PS机)用户的数据。在SQL注入攻击里,恶意用户通过SQL元数据绑定输入,比如:某个网站的登录验证SQL查询代码为:

    strSQL = "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';"

     恶意填入:

    userName = "1' OR '1'='1";
    passWord = "1' OR '1'='1"

    那么最终SQL语句变成了:

    strSQL = "SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"

     因为WHERE条件恒为真,这就相当于执行:

    strSQL = "SELECT * FROM users;"

     因此可以达到无账号密码亦可登录网站。如果恶意用户要是更坏一点,再在后面加一句  :

    drop  table users;

    SQL语句变成了:

    strSQL = "SELECT * FROM users;drop  table users;

     这样一来,虽然没有登录,但是数据表都被删除了。

       然而使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入。在使用参数化查询的情况下,数据库系统(eg:MySQL)不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,参数只是用作参数,而不会作为指令拼成SQL语句,因此就算参数中含有破坏性的指令,也不会被数据库所运行。
    补充:避免SQL注入的第二种方式:
    在组合SQL字符串的时候,先对所传入的参数做字符取代(将单引号字符取代为连续2个单引号字符,因为连续2个单引号字符在SQL数据库中会视为字符中的一个单引号字符,譬如:

    strSQL = "SELECT * FROM users WHERE name = '" + userName + "';"

     传入字符串:

    userName  = " 1' OR 1=1 "

    把userName做字符替换后变成:

    userName = " 1'' OR 1=1"

    最后生成的SQL查询语句为:

    strSQL = "SELECT * FROM users WHERE name = '1'' OR 1=1'

    这样数据库就会去系统查找name为“     1′ OR 1=1     ”的记录,而避免了SQL注入。

    CallableStatement使用:

      

    public class Conn {
        public static String URL;
        public static String USERNAME;
        public static String PASSWORD;
        public static String DRIVER;
        private static  ResourceBundle resourceBundle = ResourceBundle.getBundle("com.util.db.db_config");
        private void Conn() {}
        static{
            URL = resourceBundle.getString("jdbc.url");
            USERNAME = resourceBundle.getString("jdbc.username");
            PASSWORD = resourceBundle.getString("jdbc.password");
            DRIVER = resourceBundle.getString("jdbc.driver");
            try {
                Class.forName(DRIVER);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        /**
         * 连接数据库,若连接失败则返回空
         * @return
         */
        public static Connection getConnection() {
            Connection conn = null;
            try {
                conn = DriverManager.getConnection(URL, USERNAME,PASSWORD);
                System.out.println("连接成功!");
            } catch (SQLException e) {
                e.printStackTrace();
                System.out.println("连接失败");
            }
            return conn;
        }
        /**
         * 关闭数据库连接
         * @param rs
         * @param st
         * @param conn
         */
        public static void close(ResultSet rs,CallableStatement cstmt,Connection conn){
            try {
                if (rs != null) {rs.close();}
                if (cstmt != null) {cstmt.close();}
                if (conn !=null) {conn.close();}
            } catch (SQLException e) {
                e.printStackTrace();
            }  
        }
        
    /**
     * 1、执行不带参数但有返回值的存储过程    
     */    
    static public  int getUserCount() {
        Connection conn = Conn.getConnection();
        CallableStatement  cstmt = null;
        int rowsCount = 0; 
        try {
            String sql = "{call getUserCount(?)}";
            //创建CallableStatement 对象
            cstmt = conn.prepareCall(sql);
            //注册输出参数
            cstmt.registerOutParameter(1,Types.INTEGER);
            //执行存储过程
            cstmt.execute();
            
            rowsCount = cstmt.getInt(1);
        } catch (SQLException e) {
            System.out.println("执行失败!");
            e.printStackTrace();
        }finally {
            Conn.close(null,cstmt, conn);
            return rowsCount;
        }
    }
    /**
     *     2、执行带参数带返回值的存储过程
     */
    static public int getUserCountCondit(String username) {
        Connection conn = Conn.getConnection();
        CallableStatement  cstmt = null;
        int rowsCount = 0; 
        try {
            String sql = "{call proc_getUserCountCondit(?,?)}";
            //创建CallableStatement 对象
            cstmt = conn.prepareCall(sql);
            //输入参数赋值
            cstmt.setString(1,username);
            //注册输出参数
            cstmt.registerOutParameter(1,Types.INTEGER);
            //执行存储过程
            cstmt.execute();
            
            rowsCount = cstmt.getInt(1);
        } catch (SQLException e) {
            System.out.println("执行失败!");
            e.printStackTrace();
        }finally {
            Conn.close(null,cstmt, conn);
            return rowsCount;
        }
    }    
    /**
     * 3、执行返回值为游标的存储过程
     */
    static public List<User> getUserListByProc(){
        Connection conn = Conn.getConnection();
        CallableStatement  cstmt = null;
        ResultSet rs = null;
        List<User> userList = new ArrayList();
        try {
            String sql = "{? = call FUNC_GETUSERNAME(?)}";
            //创建CallableStatement 对象
            cstmt = conn.prepareCall(sql);
            //注册输出参数
            cstmt.registerOutParameter(1,Types.REF_CURSOR);
            //执行存储过程
            cstmt.execute();
            rs = cstmt.getResultSet();
    
            while (rs.next()) {
                String username = rs.getString("username");
                String password = rs.getString("password");
                userList.add(new User(username, password));        
            }
        } catch (SQLException e) {
            System.out.println("执行失败!");
            e.printStackTrace();
        }finally {
            Conn.close(rs,cstmt, conn);
            return userList;
        }
    }
    public static void main(String[] args) {
        
        
    
        
    }
    
    
    static class User{
        String username = null;
        String password = null;
        
        public User(String username, String password) {
            super();
            this.username = username;
            this.password = password;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        
    }
    }
  • 相关阅读:
    commands.getstatusoutput和subprocess.call结果不一致
    win10 企业版 2015 长期服务激活
    pycharm设置护眼模式
    实战--滚动菜单
    javascript中this的用法
    jQuery之remove与empty的区别
    clone方法案例实践
    jQuery内部插入与外部插入
    jQuery文档处理
    2020/02/11星期二复习
  • 原文地址:https://www.cnblogs.com/the-wang/p/7535195.html
Copyright © 2011-2022 走看看