jdbc增删改查,利用反射查询
整理自http://blog.csdn.net/yanzi1225627/article/details/26950615,谢谢作者!
本文我的爱点是:
1.利用反射实现数据库数据查询
2.编写一个sql语句,其中的参数用?来代替,然后将参数写到List里
例如使用例子:
1 String sql = "delete from userinfo where username = ?"; 2 List<Object> params = new ArrayList<Object>(); 3 params.add("小明"); 4 boolean flag = jdbcUtils.updateByPreparedStatement(sql, params);
1 /** 2 * 增加、删除、改 3 * @param sql 4 * @param params 5 * @return 6 * @throws SQLException 7 */ 8 public boolean updateByPreparedStatement(String sql, List<Object>params)throws SQLException{ 9 boolean flag = false; 10 int result = -1; 11 pstmt = connection.prepareStatement(sql); 12 int index = 1; 13 if(params != null && !params.isEmpty()){ 14 for(int i=0; i<params.size(); i++){ 15 pstmt.setObject(index++, params.get(i)); 16 } 17 } 18 result = pstmt.executeUpdate(); 19 flag = result > 0 ? true : false; 20 return flag; 21 }
JdbcUtils.java
完成对数据库的增删改查。其中查询这块,包括普通的查询和利用反射完成的查询,主要包括以下几个函数接口:
1、public Connection getConnection() 获得数据库的连接
2、public boolean updateByPreparedStatement(String sql, List<Object>params)throws SQLException 更新数据库,包括增加记录、删除记录、改动某个记录三个功能。
3、public Map<String, Object> findSimpleResult(String sql, List<Object> params) throws SQLException 查询单条记录,传进去的是一个List<Object>参数填充占位符,返回的是一个Map<String, Object>.一个Map对应一条完整的记录,String对应属性名,Object是属性值。
4、public List<Map<String, Object>> findModeResult(String sql, List<Object> params) throws SQLException 查询多条记录,放在List里。
上面四个函数已经包括了MySQl的所有操作,完全能够满足使用需要。视频里老罗还扩展了两个反射来查询的函数。
5、public <T> T findSimpleRefResult(String sql, List<Object> params,
Class<T> cls )throws Exception 利用反射查询单个记录。
6、 public <T> List<T> findMoreRefResult(String sql, List<Object> params,
Class<T> cls )throws Exception 利用反射查询多个记录。
源码:
1 import java.lang.reflect.Field; 2 import java.sql.Connection; 3 import java.sql.DriverManager; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.ResultSetMetaData; 7 import java.sql.SQLException; 8 import java.util.ArrayList; 9 import java.util.HashMap; 10 import java.util.List; 11 import java.util.Map; 12 13 import domain.UserInfo; 14 15 16 public class JdbcUtils { 17 //数据库用户名 18 private static final String USERNAME = "root"; 19 //数据库密码 20 private static final String PASSWORD = "yanzi"; 21 //驱动信息 22 private static final String DRIVER = "com.mysql.jdbc.Driver"; 23 //数据库地址 24 private static final String URL = "jdbc:mysql://localhost:3306/mydb"; 25 private Connection connection; 26 private PreparedStatement pstmt; 27 private ResultSet resultSet; 28 public JdbcUtils() { 29 // TODO Auto-generated constructor stub 30 try{ 31 Class.forName(DRIVER); 32 System.out.println("数据库连接成功!"); 33 34 }catch(Exception e){ 35 36 } 37 } 38 39 /** 40 * 获得数据库的连接 41 * @return 42 */ 43 public Connection getConnection(){ 44 try { 45 connection = DriverManager.getConnection(URL, USERNAME, PASSWORD); 46 } catch (SQLException e) { 47 // TODO Auto-generated catch block 48 e.printStackTrace(); 49 } 50 return connection; 51 } 52 53 54 /** 55 * 增加、删除、改 56 * @param sql 57 * @param params 58 * @return 59 * @throws SQLException 60 */ 61 public boolean updateByPreparedStatement(String sql, List<Object>params)throws SQLException{ 62 boolean flag = false; 63 int result = -1; 64 pstmt = connection.prepareStatement(sql); 65 int index = 1; 66 if(params != null && !params.isEmpty()){ 67 for(int i=0; i<params.size(); i++){ 68 pstmt.setObject(index++, params.get(i)); 69 } 70 } 71 result = pstmt.executeUpdate(); 72 flag = result > 0 ? true : false; 73 return flag; 74 } 75 76 /** 77 * 查询单条记录 78 * @param sql 79 * @param params 80 * @return 81 * @throws SQLException 82 */ 83 public Map<String, Object> findSimpleResult(String sql, List<Object> params) throws SQLException{ 84 Map<String, Object> map = new HashMap<String, Object>(); 85 int index = 1; 86 pstmt = connection.prepareStatement(sql); 87 if(params != null && !params.isEmpty()){ 88 for(int i=0; i<params.size(); i++){ 89 pstmt.setObject(index++, params.get(i)); 90 } 91 } 92 resultSet = pstmt.executeQuery();//返回查询结果 93 ResultSetMetaData metaData = resultSet.getMetaData(); 94 int col_len = metaData.getColumnCount(); 95 while(resultSet.next()){ 96 for(int i=0; i<col_len; i++ ){ 97 String cols_name = metaData.getColumnName(i+1); 98 Object cols_value = resultSet.getObject(cols_name); 99 if(cols_value == null){ 100 cols_value = ""; 101 } 102 map.put(cols_name, cols_value); 103 } 104 } 105 return map; 106 } 107 108 /**查询多条记录 109 * @param sql 110 * @param params 111 * @return 112 * @throws SQLException 113 */ 114 public List<Map<String, Object>> findModeResult(String sql, List<Object> params) throws SQLException{ 115 List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); 116 int index = 1; 117 pstmt = connection.prepareStatement(sql); 118 if(params != null && !params.isEmpty()){ 119 for(int i = 0; i<params.size(); i++){ 120 pstmt.setObject(index++, params.get(i)); 121 } 122 } 123 resultSet = pstmt.executeQuery(); 124 ResultSetMetaData metaData = resultSet.getMetaData(); 125 int cols_len = metaData.getColumnCount(); 126 while(resultSet.next()){ 127 Map<String, Object> map = new HashMap<String, Object>(); 128 for(int i=0; i<cols_len; i++){ 129 String cols_name = metaData.getColumnName(i+1); 130 Object cols_value = resultSet.getObject(cols_name); 131 if(cols_value == null){ 132 cols_value = ""; 133 } 134 map.put(cols_name, cols_value); 135 } 136 list.add(map); 137 } 138 139 return list; 140 } 141 142 /**通过反射机制查询单条记录 143 * @param sql 144 * @param params 145 * @param cls 146 * @return 147 * @throws Exception 148 */ 149 public <T> T findSimpleRefResult(String sql, List<Object> params, 150 Class<T> cls )throws Exception{ 151 T resultObject = null; 152 int index = 1; 153 pstmt = connection.prepareStatement(sql); 154 if(params != null && !params.isEmpty()){ 155 for(int i = 0; i<params.size(); i++){ 156 pstmt.setObject(index++, params.get(i)); 157 } 158 } 159 resultSet = pstmt.executeQuery(); 160 ResultSetMetaData metaData = resultSet.getMetaData(); 161 int cols_len = metaData.getColumnCount(); 162 while(resultSet.next()){ 163 //通过反射机制创建一个实例 164 resultObject = cls.newInstance(); 165 for(int i = 0; i<cols_len; i++){ 166 String cols_name = metaData.getColumnName(i+1); 167 Object cols_value = resultSet.getObject(cols_name); 168 if(cols_value == null){ 169 cols_value = ""; 170 } 171 Field field = cls.getDeclaredField(cols_name); 172 field.setAccessible(true); //打开javabean的访问权限 173 field.set(resultObject, cols_value); 174 } 175 } 176 return resultObject; 177 178 } 179 180 /**通过反射机制查询多条记录 181 * @param sql 182 * @param params 183 * @param cls 184 * @return 185 * @throws Exception 186 */ 187 public <T> List<T> findMoreRefResult(String sql, List<Object> params, 188 Class<T> cls )throws Exception { 189 List<T> list = new ArrayList<T>(); 190 int index = 1; 191 pstmt = connection.prepareStatement(sql); 192 if(params != null && !params.isEmpty()){ 193 for(int i = 0; i<params.size(); i++){ 194 pstmt.setObject(index++, params.get(i)); 195 } 196 } 197 resultSet = pstmt.executeQuery(); 198 ResultSetMetaData metaData = resultSet.getMetaData(); 199 int cols_len = metaData.getColumnCount(); 200 while(resultSet.next()){ 201 //通过反射机制创建一个实例 202 T resultObject = cls.newInstance(); 203 for(int i = 0; i<cols_len; i++){ 204 String cols_name = metaData.getColumnName(i+1); 205 Object cols_value = resultSet.getObject(cols_name); 206 if(cols_value == null){ 207 cols_value = ""; 208 } 209 Field field = cls.getDeclaredField(cols_name); 210 field.setAccessible(true); //打开javabean的访问权限 211 field.set(resultObject, cols_value); 212 } 213 list.add(resultObject); 214 } 215 return list; 216 } 217 218 /** 219 * 释放数据库连接 220 */ 221 public void releaseConn(){ 222 if(resultSet != null){ 223 try{ 224 resultSet.close(); 225 }catch(SQLException e){ 226 e.printStackTrace(); 227 } 228 } 229 } 230 231 /** 232 * @param args 233 */ 234 public static void main(String[] args) throws SQLException { 235 // TODO Auto-generated method stub 236 JdbcUtils jdbcUtils = new JdbcUtils(); 237 jdbcUtils.getConnection(); 238 239 /*******************增*********************/ 240 /* String sql = "insert into userinfo (username, pswd) values (?, ?), (?, ?), (?, ?)"; 241 List<Object> params = new ArrayList<Object>(); 242 params.add("小明"); 243 params.add("123xiaoming"); 244 params.add("张三"); 245 params.add("zhangsan"); 246 params.add("李四"); 247 params.add("lisi000"); 248 try { 249 boolean flag = jdbcUtils.updateByPreparedStatement(sql, params); 250 System.out.println(flag); 251 } catch (SQLException e) { 252 // TODO Auto-generated catch block 253 e.printStackTrace(); 254 }*/ 255 256 257 /*******************删*********************/ 258 //删除名字为张三的记录 259 /* String sql = "delete from userinfo where username = ?"; 260 List<Object> params = new ArrayList<Object>(); 261 params.add("小明"); 262 boolean flag = jdbcUtils.updateByPreparedStatement(sql, params);*/ 263 264 /*******************改*********************/ 265 //将名字为李四的密码改了 266 /* String sql = "update userinfo set pswd = ? where username = ? "; 267 List<Object> params = new ArrayList<Object>(); 268 params.add("lisi88888"); 269 params.add("李四"); 270 boolean flag = jdbcUtils.updateByPreparedStatement(sql, params); 271 System.out.println(flag);*/ 272 273 /*******************查*********************/ 274 //不利用反射查询多个记录 275 /* String sql2 = "select * from userinfo "; 276 List<Map<String, Object>> list = jdbcUtils.findModeResult(sql2, null); 277 System.out.println(list);*/ 278 279 //利用反射查询 单条记录 280 String sql = "select * from userinfo where username = ? "; 281 List<Object> params = new ArrayList<Object>(); 282 params.add("李四"); 283 UserInfo userInfo; 284 try { 285 userInfo = jdbcUtils.findSimpleRefResult(sql, params, UserInfo.class); 286 System.out.print(userInfo); 287 } catch (Exception e) { 288 // TODO Auto-generated catch block 289 e.printStackTrace(); 290 } 291 292 293 } 294 295 }
对应的JavaBean UserInfo.java
1 import java.io.Serializable; 2 3 public class UserInfo implements Serializable{ 4 5 /** 6 * 7 */ 8 private static final long serialVersionUID = 1L; 9 10 private int id; 11 private String username; 12 private String pswd; 13 14 public UserInfo() { 15 // TODO Auto-generated constructor stub 16 } 17 18 public int getId() { 19 return id; 20 } 21 22 public void setId(int id) { 23 this.id = id; 24 } 25 26 public String getUsername() { 27 return username; 28 } 29 30 public void setUsername(String username) { 31 this.username = username; 32 } 33 34 public String getPswd() { 35 return pswd; 36 } 37 38 public void setPswd(String pswd) { 39 this.pswd = pswd; 40 } 41 42 @Override 43 public String toString() { 44 return "UserInfo [id=" + id + ", username=" + username + ", pswd=" 45 + pswd + "]"; 46 } 47 48 49 50 51 52 }
1.抛开以上来说,操作数据库的一般性步骤如下:
(1)连接数据库,加载驱动: Class.forName(DRIVER); DRIVER = "com.mysql.jdbc.Driver";这本身就是反射!!
(2) 利用用户名和密码及数据库的名字连接,这一步才是真正的连接:
connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
其中:String URL = "jdbc:mysql://localhost:3306/mydb";
(3)编写一个sql语句,其中的参数用?来代替,然后将参数写到List里。
执行:pstmt = connection.prepareStatement(sql); 然后将参数从list里取出来填充到pstmt里。
(4)如果是增、删、改执行:result = pstmt.executeUpdate(); 其中的result是执行完影响的数据库里的行数,也即几条记录。
如果是查询执行:resultSet = pstmt.executeQuery(); 返回的类型是ResultSet类型。之后就是把resultSet 弄成Map或List<Map>传递出去,给查询者看。
2.关于查询操作,在得到resultSet后利用getMetaData得到表的结构信息,如getColumnCount()得到有多少个列。String cols_name = metaData.getColumnName(i+1); 得到每个列的属性名称,如是id、username还是pswd.然后从Object cols_value = resultSet.getObject(cols_name);取出来,放到Map或List<Map>里。
3.关于查询里利用的反射操作,步骤如下:
(1) T resultObject = cls.newInstance(); 利用class文件的newInstance()方法创建一个实例。
(2)在通过getColumnCount()得到有多少个列之后,进入循环,
String cols_name = metaData.getColumnName(i+1);
Object cols_value = resultSet.getObject(cols_name);
读取每一列的属性名字和放的值。通过属性的名字cols_name进行反射:Field field = cls.getDeclaredField(cols_name);这样就得到了Field 等于类里的成员变量, field.setAccessible(true); //打开javabean的访问权限 在利用set方法将从数据库中查出来的cols_value通过JavaBean 也即定义的UserInfo这个类的 set方法赋进去。 field.set(resultObject, cols_value);
4.一般意义上,要利用Java的反射需要以下步骤
(1)加载Class对象,这个一般有两种方式:Class cls1 = UserInfo.class 或
Class cls2 = Class.forName("domain.UserInfo") 后者是利用包名+类名的方法。
(2)反射出来Class之后干啥事呢?一个类不外乎构造函数、成员变量、成员函数。所以得到Class之后就可以干这三件事。
A、关于构造函数,获得Constructor 有四种方法:
Constructor getConstructor(Class[] params)
Constructor[] getConstructors()
Constructor getDeclaredConstructor(Class[] params)
Constructor[] getDeclaredConstructors()
这四个函数,如果不传参数则是获得所有的构造函数,得到的是一个集合。如果传特定的参数,则是寻找这个特定的构造函数,不带Declared是获得公共的public,带了Declared是可以获得私有构造函数。 得到构造函数后就可以利用反射创建实例了:
Constructor con1[] = cls1.getDeclaredConstructors();
con1[1].setAccessible(true);
Object obj1 = con1[1].newInstance(new Object[]{"tom"}); 如果直接调用clcs.newInstance()则是用默认的构造函数创建实例。
B、关于成员变量,同样有四种方法:
public Field getDeclaredField(String name) 获取任意指定名字的成员
public Field[] getDeclaredFields() 获取所有的成员变量
public Field getField(String name) 获取任意public成员变量
public Field[] getFields() 获取所有的public成员变量
本文封装的JdbcUtils类就是利用这种方式操作类里的私有成员变量,记得要setAccessible打开开关。如下:
Field field = cls.getDeclaredField(cols_name);
field.setAccessible(true); //打开javabean的访问权限
field.set(resultObject, cols_value);
C、关于成员函数,也有四种方法:
public Method[] getMethods() 获取所有的共有方法的集合
public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 ,
参数1:方法名 参数2:参数类型集合
public Method[] getDeclaredMethods() 获取所有的方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法
下面是利用文中的UserInfo这个类写的一个完成的反射例子,拿到setUsername(String username)方法,然后反射。再拿到getUsername()方法再反射,然后打印出结果:
Class clcs = UserInfo.class;
try {
Object obj = clcs.newInstance();
Method f = clcs.getDeclaredMethod("setUsername", String.class);
f.invoke(obj, "yan123");
Method f2 = clcs.getDeclaredMethod("getUsername", null);
Object name = f2.invoke(obj, null);
System.out.println("反射得到的名字 = " + name);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
在反射方法的时候,Method f = clcs.getDeclaredMethod("setUsername", String.class); 原函数里的输入参数是什么类型,就写什么类型.class. 如原来的setXXX需要输入参数String,反射的时候就写String.class.
5. JavaBean是反射的一种,反射对构造函数之类的没任何要求,JavaBean要求这个类必须继承Serializable即可串行化,另外构造函数必须为public. 另外,就是JavaBean在得到某个field后可以直接调用set和get,而不必再反射得到method后再执行。
最后,反射是在程序运行的时候而非编译时!!!
谢谢作者:http://blog.csdn.net/yanzi1225627/article/details/26950615