优化JDBC封装
Posted 遗风遗风丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优化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 }
测试结果:
相应数据库:
以上是关于优化JDBC封装的主要内容,如果未能解决你的问题,请参考以下文章
VSCode自定义代码片段14——Vue的axios网络请求封装
VSCode自定义代码片段14——Vue的axios网络请求封装