一、元數據
元數據:數據庫、表、列的定義信息
1、DataBaseMetaData對象
getURL():返回一個String類對象,代表數據庫的URL。
getUserName():返回連接當前數據庫管理系統的用戶名。
getDatabaseProductName():返回數據庫的產品名稱。
getDatabaseProductVersion():返回數據庫的版本號。
getDriverName():返回驅動驅動程序的名稱。
getDriverVersion():返回驅動程序的版本號。
isReadOnly():返回一個boolean值,指示數據庫是否只允許讀操作。
1 /**
2 * 獲取數據庫的元數據 3 * @throws SQLException 4 */
5 @Test 6 public void test1() throws SQLException{ 7 Connection con = JdbcUtils_DBCP.getConnection(); 8
9 //獲取數據庫的元數據
10 DatabaseMetaData meta = con.getMetaData(); 11 //獲取數據庫的版本
12 System.out.println(meta.getDatabaseMajorVersion()); 13 //獲取數據庫的產品名稱
14 System.out.println(meta.getDatabaseProductName()); 15 //獲取數據庫默認的隔離級別
16 System.out.println(meta.getDefaultTransactionIsolation()); 17
18 /**
19 * 結果: 20 * 5 21 MySQL 22 2 23 * 24 */
25 }
2、 ParameterMetaData對象
PreparedStatement . getParameterMetaData()
獲得代表PreparedStatement元數據的ParameterMetaData對象。
Select * from user where name=? And password=?
ParameterMetaData對象
getParameterCount()
獲得指定參數的個數
getParameterType(int param)
獲得指定參數的sql類型
1 /**
2 * 獲取參數元數據 3 * @throws SQLException 4 */
5 @Test 6 public void test2() throws SQLException{ 7 Connection con = JdbcUtils_DBCP.getConnection(); 8 String sql = "insert into account(name,money) values(?,?)"; 9 //預編譯sql語句
10 PreparedStatement ps = con.prepareStatement(sql); 11 //獲取參數元數據
12 ParameterMetaData meta = ps.getParameterMetaData(); 13
14 //獲取參數的個數 結果:2
15 System.out.println(meta.getParameterCount()); 16
17 //獲取參數的類型
18 System.out.println(meta.getParameterType(1)); 19 } 20
3、ResultSetMetaData對象
ResultSet. getMetaData()
獲得代表ResultSet對象元數據的ResultSetMetaData對象。
ResultSetMetaData對象
getColumnCount()
返回resultset對象的列數
getColumnName(int column)
獲得指定列的名稱
getColumnTypeName(int column)
獲得指定列的類型
1 /*
2 * 獲取結果集元數據 3 */
4
5 @Test 6 public void test3() throws SQLException{ 7 Connection con = JdbcUtils_DBCP.getConnection(); 8 String sql = "select * from account"; 9 //預編譯sql語句
10 PreparedStatement ps = con.prepareStatement(sql); 11 ResultSet rs = ps.executeQuery(); 12
13 //獲取元數據
14 ResultSetMetaData meta = rs.getMetaData(); 15 System.out.println(meta.getColumnCount()); 16 System.out.println(meta.getColumnName(1)); 17 System.out.println(meta.getColumnName(2)); 18 System.out.println(meta.getColumnName(3)); 19
20 //結果:id name money
21 }
二、對JDBC進行優化
1、對增、刪、改進行優化
所有實體的CUD操作代碼基本相同,僅僅發送給數據庫的SQL語句不同而已,因此可以把CUD操作的所有相同代碼抽取到工具類的一個update方法中,並定義參數接收變化的SQL語句。
1 //優化JDBC的增、刪、改
2 /**
3 * 4 * @param sql 接受參數 5 * @param params 參數 替換掉sql語句的?號 6 * @throws SQLException 7 */
8 public static void create_delete_update(String sql,Object params[]) throws SQLException{ 9 Connection con = null; 10 PreparedStatement st = null; 11 ResultSet result = null; 12
13 try{ 14 con = getConnection(); 15 st = con.prepareStatement(sql); 16
17 //把sql的?號替換掉
18 for(int i=0;i<params.length;i++){ 19
20 //因為不清楚表的列數據是什么類型,所以用Object
21 st.setObject(i+1,params[i]); 22 } 23
24 st.executeUpdate(); 25
26 }finally{ 27 release(con, st, result); 28 } 29 }
2、對查找進行優化
1 //優化sql查詢
2 public static Object query(String sql,Object params[],ResultSetHandler handler) throws SQLException{ 3 Connection con = null; 4 PreparedStatement st = null; 5 ResultSet rs = null; 6 try{ 7 con = getConnection(); 8 st = con.prepareStatement(sql); 9 //替代問號
10 for(int i=0;i<params.length;i++){ 11 st.setObject(i+1, params[i]); 12 } 13
14 //執行
15 rs = st.executeQuery(); 16
17 //由於不知道調用者怎么處理結果集,所有由調用者調用時傳入一個處理器對象,調用處理器對象的處理方法
18 return handler.handler(rs); 19 }finally{ 20 release(con, st, rs); 21 } 22 } 23
24 } 25
26
27 //暴露接口
28 interface ResultSetHandler{ 29 public Object handler(ResultSet rs); 30 } 31
32 //實現把結果封裝到bean里面,適用於查找一條數據
33 class BeanHandler implements ResultSetHandler{ 34 Class clazz; 35 public BeanHandler(Class clazz){ 36 this.clazz = clazz; 37 } 38
39 //處理方法,把數據封裝到javabean
40 public Object handler(ResultSet rs) { 41 try { 42 if(!rs.next()){ 43 return null; 44 } 45
46 //創建封裝結果的bean對象
47 Object bean = clazz.newInstance(); 48
49 //得到結果集數的元數據,已獲取結果集的信息
50 ResultSetMetaData meta = rs.getMetaData(); 51
52 //得到結果集的列數
53 int count = meta.getColumnCount(); 54
55 //for循環賦值給bean對象
56 for(int i=0;i<count;i++){ 57 String name = meta.getColumnName(i+1); 58 Object value = rs.getObject(name); 59
60 //反射出bean上與列名相應的屬性
61 Field f = bean.getClass().getDeclaredField(name); 62 //由於屬性是私有的,要把屬性設置成可見的
63 f.setAccessible(true); 64 //設置屬性
65 f.set(bean, value); 66 } 67
68 return bean; 69 } catch (Exception e) { 70 throw new RuntimeException(e); 71 } 72 } 73 } 74
75 //把結果封裝到一個集合里面去
76 class BeanListHandler implements ResultSetHandler{ 77 Class clazz; 78 public BeanListHandler(Class clazz){ 79 this.clazz = clazz; 80 } 81
82 public Object handler(ResultSet rs){ 83 List list = new ArrayList(); 84 try{ 85 while(rs.next()){ 86 //創建bean對象
87 Object bean = clazz.newInstance(); 88 ResultSetMetaData meta = rs.getMetaData(); 89
90 //獲取列數
91 int count = meta.getColumnCount(); 92 for(int i=0;i<count;i++){ 93 //列名
94 String name = meta.getColumnName(i+1); 95 Object value = rs.getObject(name); 96 Field f = bean.getClass().getDeclaredField(name); 97 f.setAccessible(true); 98 f.set(bean, value); 99 } 100 list.add(bean); 101 } 102 }catch(Exception e){ 103 throw new RuntimeException(e); 104 } 105 return list; 106 } 107 }
3、完整代碼
1 package com.utils; 2 import java.io.InputStream; 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.ResultSetMetaData; 9 import java.sql.SQLException; 10 import java.sql.Statement; 11 import java.util.ArrayList; 12 import java.util.List; 13 import java.util.Properties; 14 import javax.sql.DataSource; 15 import org.apache.commons.dbcp.BasicDataSourceFactory; 16
17 public class DButils { 18
19 //數據庫連接池
20 private static DataSource ds = null; 21 static{ 22 try{ 23 //讀取配置文件
24 InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); 25 Properties prop = new Properties(); 26 prop.load(in); 27 BasicDataSourceFactory factory = new BasicDataSourceFactory(); 28 //創建連接池
29 ds = factory.createDataSource(prop); 30 }catch(Exception e){ 31 throw new ExceptionInInitializerError(e); 32 } 33 } 34
35
36 //獲取連接
37 public static Connection getConnection() throws SQLException{ 38
39 return ds.getConnection(); 40 } 41
42 //釋放資源
43 public static void release(Connection con,Statement st,ResultSet result){ 44 if(result!=null){ 45 try { 46 result.close(); 47 } catch (Exception e) { 48 e.printStackTrace(); 49 } 50 result = null; 51 } 52
53 if(st!=null){ 54 try { 55 st.close(); 56 } catch (Exception e) { 57 e.printStackTrace(); 58 } 59 st = null; 60 } 61
62 if(con!=null){ 63 try { 64 con.close(); 65 } catch (Exception e) { 66 e.printStackTrace(); 67 } 68
69 } 70 } 71
72
73 //優化JDBC的增、刪、改
74 /**
75 * 76 * @param sql 接受參數 77 * @param params 參數 替換掉sql語句的?號 78 * @throws SQLException 79 */
80 public static void create_delete_update(String sql,Object params[]) throws SQLException{ 81 Connection con = null; 82 PreparedStatement st = null; 83 ResultSet result = null; 84
85 try{ 86 con = getConnection(); 87 st = con.prepareStatement(sql); 88
89 //把sql的?號替換掉
90 for(int i=0;i<params.length;i++){ 91
92 //因為不清楚表的列數據是什么類型,所以用Object
93 st.setObject(i+1,params[i]); 94 } 95
96 st.executeUpdate(); 97
98 }finally{ 99 release(con, st, result); 100 } 101 } 102
103
104 //優化sql查詢
105 public static Object query(String sql,Object params[],ResultSetHandler handler) throws SQLException{ 106 Connection con = null; 107 PreparedStatement st = null; 108 ResultSet rs = null; 109 try{ 110 con = getConnection(); 111 st = con.prepareStatement(sql); 112 //替代問號
113 for(int i=0;i<params.length;i++){ 114 st.setObject(i+1, params[i]); 115 } 116
117 //執行
118 rs = st.executeQuery(); 119
120 //由於不知道調用者怎么處理結果集,所有由調用者調用時傳入一個處理器對象,調用處理器對象的處理方法
121 return handler.handler(rs); 122 }finally{ 123 release(con, st, rs); 124 } 125 } 126
127 } 128
129
130 //暴露接口
131 interface ResultSetHandler{ 132 public Object handler(ResultSet rs); 133 } 134
135 //實現把結果封裝到bean里面,適用於查找一條數據
136 class BeanHandler implements ResultSetHandler{ 137 Class clazz; 138 public BeanHandler(Class clazz){ 139 this.clazz = clazz; 140 } 141
142 //處理方法,把數據封裝到javabean
143 public Object handler(ResultSet rs) { 144 try { 145 if(!rs.next()){ 146 return null; 147 } 148
149 //創建封裝結果的bean對象
150 Object bean = clazz.newInstance(); 151
152 //得到結果集數的元數據,已獲取結果集的信息
153 ResultSetMetaData meta = rs.getMetaData(); 154
155 //得到結果集的列數
156 int count = meta.getColumnCount(); 157
158 //for循環賦值給bean對象
159 for(int i=0;i<count;i++){ 160 String name = meta.getColumnName(i+1); 161 Object value = rs.getObject(name); 162
163 //反射出bean上與列名相應的屬性
164 Field f = bean.getClass().getDeclaredField(name); 165 //由於屬性是私有的,要把屬性設置成可見的
166 f.setAccessible(true); 167 //設置屬性
168 f.set(bean, value); 169 } 170
171 return bean; 172 } catch (Exception e) { 173 throw new RuntimeException(e); 174 } 175 } 176 } 177
178 //把結果封裝到一個集合里面去
179 class BeanListHandler implements ResultSetHandler{ 180 Class clazz; 181 public BeanListHandler(Class clazz){ 182 this.clazz = clazz; 183 } 184
185 public Object handler(ResultSet rs){ 186 List list = new ArrayList(); 187 try{ 188 while(rs.next()){ 189 //創建bean對象
190 Object bean = clazz.newInstance(); 191 ResultSetMetaData meta = rs.getMetaData(); 192
193 //獲取列數
194 int count = meta.getColumnCount(); 195 for(int i=0;i<count;i++){ 196 //列名
197 String name = meta.getColumnName(i+1); 198 Object value = rs.getObject(name); 199 Field f = bean.getClass().getDeclaredField(name); 200 f.setAccessible(true); 201 f.set(bean, value); 202 } 203 list.add(bean); 204 } 205 }catch(Exception e){ 206 throw new RuntimeException(e); 207 } 208 return list; 209 } 210 } 211
212
213
214
215
測試:
1 package com.utils; 2
3 import java.sql.SQLException; 4 import java.util.Iterator; 5 import java.util.List; 6
7 import org.junit.Test; 8
9 import com.domain.Account; 10
11 public class Demo { 12
13 //測試添加
14 @Test 15 public void testAdd() throws SQLException{ 16 Account a = new Account(); 17 a.setName("陳海宏"); 18 a.setMoney(30); 19 add(a); 20 } 21
22 @Test 23 //測試刪除
24 public void testDelete() throws SQLException{ 25 delete(1); 26 } 27
28 @Test 29 //測試更改
30 public void testUpdate() throws SQLException{ 31 Account a = new Account(); 32 a.setId(2); 33 a.setName("王五"); 34 a.setMoney(30); 35 update(a); 36 } 37
38 @Test 39 //測試查找單項記錄
40 public void testFind() throws SQLException{ 41 Account a = find(7); 42 System.out.println(a.getName()); 43 } 44
45
46
47
48 //測試查找單記錄
49 @Test 50 public void testGetAll() throws SQLException{ 51 List list = getAll(); 52 //對集合進行迭代
53 Iterator it = list.iterator(); 54 while(it.hasNext()){ 55 Account a = (Account) it.next(); 56 System.out.println(a.getId()+"+"+a.getName()+"+"+a.getMoney()); 57
58 } 59 } 60
61
62
63 //添加
64 public void add(Account a) throws SQLException{ 65
66 //准備sql語句
67 String sql = "insert into account(name,money) values(?,?)"; 68 //替換?的參數數據
69 Object params[] = {a.getName(),a.getMoney()}; 70 DButils.create_delete_update(sql, params); 71
72 } 73
74 //刪除
75 public void delete(int id) throws SQLException{ 76
77 //准備sql語句
78 String sql = "delete from account where id=?"; 79 //替換?的參數數據
80 Object params[] = {id}; 81 DButils.create_delete_update(sql, params); 82 } 83
84 //更新
85 public void update(Account a) throws SQLException{ 86 String sql = "update account set name = ?,money = ? where id=?"; 87 Object params[] = {a.getName(),a.getMoney(),a.getId()}; 88 DButils.create_delete_update(sql, params); 89 } 90
91 //查找單項記錄
92 public Account find(int i) throws SQLException{ 93 String sql = "select * from account where id=?"; 94 Object params[] = {i}; 95 return (Account) DButils.query(sql, params,new BeanHandler(Account.class)); 96 } 97
98 //查找所有記錄
99 public List getAll() throws SQLException{ 100 String sql = "select * from account"; 101 Object params[] = {}; 102 return (List) DButils.query(sql, params,new BeanListHandler(Account.class)); 103 } 104 }