• 优化JDBC封装


    可重用性较强的JDBC封装

    以下为代码,注释中写了主要思想

    主类

    com.util.JDBCUtil.java

      1 package com.util;
      2 
      3 import java.lang.reflect.Field;
      4 import java.sql.Connection;
      5 import java.sql.DriverManager;
      6 import java.sql.PreparedStatement;
      7 import java.sql.ResultSet;
      8 import java.sql.SQLException;
      9 import java.util.ArrayList;
     10 import java.util.Arrays;
     11 import java.util.List;
     12 
     13 public class JDBCUtil {
     14     private final static String driver="com.mysql.jdbc.Driver";
     15     private final static String url="jdbc:mysql://192.168.137.11:3306/db_test?useUnicode=true&characterEncoding=utf8";
     16     private final static String user="root";
     17     private final static String password="123456";
     18     //获取JDBC连接
     19     public static Connection getConnection(){
     20         Connection conn=null;
     21         try {
     22             Class.forName(driver);
     23             conn=DriverManager.getConnection(url,user,password);
     24             
     25         } catch (ClassNotFoundException e) {
     26             // TODO 自动生成的 catch 块
     27             e.printStackTrace();
     28         } catch (SQLException e) {
     29             // TODO 自动生成的 catch 块
     30             e.printStackTrace();
     31         }
     32         return conn;
     33     }
     34     //关闭连接
     35     public static void close(Connection conn,PreparedStatement pstmt,ResultSet rs){
     36         if(rs!=null){
     37             try {
     38                 rs.close();
     39             } catch (SQLException e) {
     40                 // TODO 自动生成的 catch 块
     41                 e.printStackTrace();
     42             }
     43         }
     44         if(pstmt!=null){
     45             try {
     46                 pstmt.close();
     47             } catch (SQLException e) {
     48                 // TODO 自动生成的 catch 块
     49                 e.printStackTrace();
     50             }
     51         }
     52         if(conn!=null){
     53             try {
     54                 conn.close();
     55             } catch (SQLException e) {
     56                 // TODO 自动生成的 catch 块
     57                 e.printStackTrace();
     58             }
     59         }
     60     }
     61     //增、删、改
     62     /*
     63      * sql语句参数部分应改为?替代,代码中使用PreparedStatement类来注入参数,防止sql注入
     64      * 因不确定sql语句参数个数,类型,所以使用动态参数Object... objects 
     65      * 将objects使用PreparedStatement中setObject方法注入
     66      * 调用时可以这样调用
     67      * update("insert into user values(?,?)","ads","asdsa");
     68      * 这样封装使得此方法可重用性强
     69      */
     70     public static int update(String sql,Object... objects ){
     71         Connection conn=getConnection();
     72         PreparedStatement pstmt=null;
     73         int result =0;
     74         
     75         try {
     76             pstmt=conn.prepareStatement(sql);
     77             if(objects!=null){
     78                 for(int i=0;i<objects.length;i++){
     79                     pstmt.setObject(i+1, objects[i]);
     80                 }
     81             }
     82             result=pstmt.executeUpdate();
     83         } catch (SQLException e) {
     84             // TODO 自动生成的 catch 块
     85             e.printStackTrace();
     86         }finally {
     87             close(conn, pstmt, null);
     88         }
     89         
     90         
     91         return result;
     92     }
     93     
     94     //添加对象
     95     /*
     96      * 不确定未来编程时向数据库中添加对象是什么,固使用泛型T    
     97      * 可以使用自定义注解的方式实现javabean与相应数据表的映射
     98      * 此方法封装时代码晦涩难懂,使用时不用自己去写sql语句较为方便且复用性强
     99      * 类似于hibernate
    100      */
    101     public static <T> int insert(T t){
    102         //列名数组,即javabean的属性,用于拼接sql语句
    103         List<String> columns=new ArrayList<>();
    104         //用于拼接sql语句,存放‘?’,若javabean有4个属性,则此数组为[?,?,?,?]
    105         List<String> values=new ArrayList<>();
    106         //存放javabean各个属性的值,最后使用PreparedStatement注入
    107         List<Object> params=new ArrayList<>();
    108         
    109         Class clz=t.getClass();
    110         //TableUtil自定义注解,用于javabean与表名的映射
    111         TableUtil ann=(TableUtil)clz.getAnnotation(TableUtil.class);
    112         //获取该javabean的属性
    113         Field[] fields=clz.getDeclaredFields();
    114         //for循环对columns values数组赋值
    115         /*
    116          * ColumnUtil自定义注解,用于javabean属性与表的列名映射
    117          * IDUtil自定义注解,用于表的自增长主键与相应javabean属性映射
    118          */
    119         for (Field field : fields) {
    120             //若数据表中设置了自增长主键,使用insert语句时须跳过相应的主属性,所以应执行此if语句判断
    121             if(!field.isAnnotationPresent(IDUtil.class)){
    122                 //判断是使用ColumnUtil将此属性映射
    123                 if(field.isAnnotationPresent(ColumnUtil.class)){
    124                     //获取列名
    125                     ColumnUtil column= field.getAnnotation(ColumnUtil.class);
    126                     //columns数组添加相应列名
    127                     columns.add(column.value());
    128                     //获取一列,便向values数组中添加一个‘?’,即有多少列就有多少个‘?’
    129                     values.add("?");
    130                     //一般javabean属性为private,使用此方法可访问private属性
    131                     field.setAccessible(true);
    132                     try {
    133                         //列相应的值,存放入params数组
    134                         params.add(field.get(t));
    135                     } catch (IllegalArgumentException | IllegalAccessException e) {
    136                         // TODO Auto-generated catch block
    137                         e.printStackTrace();
    138                     }
    139                 }
    140             }
    141         }
    142         /*
    143          * 拼接sql语句
    144          * ann.value()即注解的表名
    145          * list数组转化为String,结果为[...],为拼接sql语句需将"[]"变"()"
    146          */
    147         String sql="insert into "+ann.value()+Arrays.toString(columns.toArray()).replaceAll("\[", "(").replaceAll("\]", ")")+" values"+Arrays.toString(values.toArray()).replaceAll("\[", "(").replaceAll("\]", ")");
    148         //System.out.println(Arrays.toString(params.toArray()) );
    149         //System.out.println(sql);
    150         
    151         //以下为执行sql语句过程
    152         //思想同上面的update方法
    153         Connection connection=getConnection();
    154         PreparedStatement preparedStatement=null;
    155         int result=0;
    156         try {
    157             preparedStatement=connection.prepareStatement(sql);
    158             for (int i=0;i<params.size();i++) {
    159                 preparedStatement.setObject(i+1,params.get(i));
    160             }
    161             result=preparedStatement.executeUpdate();
    162             
    163         } catch (SQLException e) {
    164             // TODO 自动生成的 catch 块
    165             e.printStackTrace();
    166         }finally {
    167             close(connection, preparedStatement, null);
    168         }
    169         
    170         return result;
    171         
    172     }
    173     
    174     //查询,获取对象列表
    175     /*
    176      * 此方法调用时,使用匿名内部类,程序员可以自己写ResultSet结果集,具有好的复用性
    177      * sql语句中参数部分使用?替代,并使用动态参数,思想同上
    178      */
    179     public static <T> List<T> executeQuery(String sql,RowMap<T> rowMap,Object...objects ){
    180         List<T> list=new ArrayList<>();
    181         Connection connection=getConnection();
    182         PreparedStatement preparedStatement=null;
    183         ResultSet rSet=null;
    184         try {
    185             preparedStatement=connection.prepareStatement(sql);
    186             if(objects!=null) {
    187                 for (int i=0;i<objects.length;i++) {
    188                     preparedStatement.setObject(i+1, objects[i]);
    189                     
    190                 }
    191             }
    192             rSet=preparedStatement.executeQuery();
    193             while (rSet.next()) {
    194                 T t=rowMap.rowMapping(rSet);
    195                 list.add(t);
    196             }
    197         } catch (SQLException e) {
    198             // TODO 自动生成的 catch 块
    199             e.printStackTrace();
    200         }finally {
    201             close(connection, preparedStatement, rSet);
    202         }
    203         
    204         return list;
    205     }
    206     
    207 }

    以下为相关工具类

    com.util.ColumnUtil.java

     1 package com.util;
     2 import java.lang.annotation.ElementType;
     3 import java.lang.annotation.Retention;
     4 import java.lang.annotation.RetentionPolicy;
     5 import java.lang.annotation.Target;
     6 @Target(ElementType.FIELD)
     7 @Retention(RetentionPolicy.RUNTIME)
     8 public @interface ColumnUtil {
     9     //相应列名
    10     String value();
    11 }

    com.util.IDUtil.java

     1 package com.util;
     2 
     3 import java.lang.annotation.ElementType;
     4 import java.lang.annotation.Retention;
     5 import java.lang.annotation.RetentionPolicy;
     6 import java.lang.annotation.Target;
     7 
     8 
     9 @Target(ElementType.FIELD)
    10 @Retention(RetentionPolicy.RUNTIME)
    11 //自增主键注解
    12 public @interface IDUtil {
    13 
    14 }

    com.util.TableUtil.java

    package com.util;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface TableUtil {
        //映射相应表名
        String value();
    }

    com.util.RowMap.java

    package com.util;
    
    import java.sql.ResultSet;
    
    public interface RowMap<T> {
        //自定义result结果集
        //使用了匿名内部类的思想
        public T rowMapping(ResultSet rs);
    }

    以下为测试类:

    com.model.User.java

    package com.model;
    
    import com.util.ColumnUtil;
    import com.util.TableUtil;
    
    @TableUtil("t_user")
    //此javabean映射表名为"t_user"
    public class User {
        @ColumnUtil("c_username")
        //属性username对应表中的c_username列
        private String username;
        //属性password对应表中的c_password列
        @ColumnUtil("c_password")
        private String password;
        public String getUsername() {
            return username;
        }
        public String getPassword() {
            return password;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        
    
    }

    tests.JDBCUtilTest.java

     1 package tests;
     2 
     3 import java.sql.ResultSet;
     4 import java.sql.SQLException;
     5 import java.util.List;
     6 import java.util.UUID;
     7 
     8 import com.model.User;
     9 import com.util.JDBCUtil;
    10 import com.util.RowMap;
    11 
    12 public class JDBCUtilTest {
    13 
    14     public static void main(String[] args) {
    15         User newUser=new User();
    16         newUser.setUsername(UUID.randomUUID().toString());
    17         newUser.setPassword("asd");
    18         JDBCUtil.insert(newUser);
    19         List<User> users=JDBCUtil.executeQuery("select * from t_user where c_username!=?",new RowMap<User>() {
    20             @Override
    21             //匿名内部类 定义resultset结果集
    22             public User rowMapping(ResultSet rs) {
    23                 User user=new User();
    24                 try {
    25                     user.setUsername(rs.getString("c_username"));
    26                     user.setPassword(rs.getString("c_password"));
    27                 } catch (SQLException e) {
    28                     e.printStackTrace();
    29                 }
    30                 return user;
    31             }
    32         }, "JDBCUtil");//查找用户名不为JDBCUtil的用户
    33         for (User user : users) {
    34             System.out.println(user.getUsername()+"&&"+user.getPassword());
    35         }
    36         
    37     }
    38 
    39 }

    测试结果:

    相应数据库:

  • 相关阅读:
    类加载机制
    PTA(BasicLevel)-1094 谷歌的招聘
    PTA(BasicLevel)-1023 组个最小数
    异构图神经网络笔记-Heterogeneous Graph Neural Network(KDD19)
    PTA(BasicLevel)-1014 福尔摩斯的约会
    PTA(BasicLevel)-1013 数素数
    PTA(BasicLevel)-1012 数字分类
    PTA(BasicLevel)-1010 一元多项式求导
    PTA(BasicLevel)-1009 说反话
    PTA(BasicLevel)-1008数组元素循环右移问题
  • 原文地址:https://www.cnblogs.com/yifengyifeng/p/9317442.html
Copyright © 2020-2023  润新知