用jdbc連接數據庫並簡單執行SQL語句


一:版本一.這種存在一個問題就是每執行一次操作都會創建一次Connection鏈接和且釋放一次鏈接

1:創建pojo對象(OR映射,一個pojo類對應一張數據庫表)

 
 1 package com.yinfu.dao;
 2  
 3  public class Employee {
 4  
 5      private int id;
 6      private String name;
 7      private String password;
 8      public int getId() {
 9          return id;
10      }
11      public void setId(int id) {
12          this.id = id;
13      }
14      public String getName() {
15          return name;
16      }
17      public void setName(String name) {
18          this.name = name;
19      }
20      public String getPassword() {
21          return password;
22      }
23      public void setPassword(String password) {
24          this.password = password;
25      }
26      @Override
27      public String toString() {
28          return "Employee [id=" + id + ", name=" + name + ", password=" + password + "]";
29      }
30      public Employee(int id, String name, String password) {
31          super();
32          this.id = id;
33          this.name = name;
34          this.password = password;
35      }
36      public Employee() {
37          super();
38      }
39  }
pojo對象

2:創建數據庫連接用的數據文件,用於外界讀取數據(properties文件):

 1 driver=com.mysql.jdbc.Driver 2 jdbcUrl=jdbc:mysql://localhost:3306/test 3 user=root 4 password=song12345 

3:創建數據庫連接和關閉連接的工具類(被重復使用的方法可以寫在工具類中):

  1 package com.yinfu.utils;
  2 
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.sql.Connection;
  6 import java.sql.DriverManager;
  7 import java.sql.PreparedStatement;
  8 import java.sql.ResultSet;
  9 import java.sql.SQLException;
 10 import java.util.Properties;
 11 /**
 12  * JDBC的工具類,封裝了jdbc的一些方法
 13  * @author lusong
 14  *
 15  */
 16 public class JDBCUtils {
 17 
 18     //關閉jdbc的鏈接
 19     /**
 20      * 關閉statement和connection
 21      * @param ps
 22      * @param conn
 23      */
 24     public static void release(PreparedStatement ps, Connection conn){
 25         try {
 26             if(ps != null){
 27                 ps.close();
 28             }
 29         } catch (SQLException e) {
 30             e.printStackTrace();
 31         }finally{
 32             try {
 33                 if(conn != null){
 34                     conn.close();
 35                 }
 36             } catch (SQLException e) {
 37                 e.printStackTrace();
 38             }
 39         }
 40     }
 41     public static void release(ResultSet result,PreparedStatement ps, Connection conn){
 42         try {
 43             if(result != null){
 44                 result.close();
 45             }
 46         } catch (SQLException e1) {
 47             e1.printStackTrace();
 48         }finally{
 49             try {
 50                 if(ps != null){
 51                     ps.close();
 52                 }
 53             } catch (SQLException e) {
 54                 e.printStackTrace();
 55             }finally{
 56                 try {
 57                     if(conn != null){
 58                         conn.close();
 59                     }
 60                 } catch (SQLException e) {
 61                     e.printStackTrace();
 62                 }
 63             }
 64         }
 65         
 66     }
 67     
 68     //獲取jdbc的鏈接
 69     /**
 70      * 用於創建jdbc鏈接的工具類對象
 71      * @return
 72      */
 73     public static Connection getConnetions() {
 74         Connection conn = null;
 75         String driverClass = null;
 76         String jdbcUrl = null;
 77         String user = null;
 78         String password = null;
 79         
 80         try {
 81             //讀取配置文件中的配置
 82             InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
 83             Properties properties = new Properties();
 84             properties.load(is);
 85             driverClass = properties.getProperty("driver");
 86             jdbcUrl = properties.getProperty("jdbcUrl");
 87             user = properties.getProperty("user");
 88             password = properties.getProperty("password");
 89             //注冊驅動程序
 90             Class.forName(driverClass);
 91             //實際應該這樣寫(由於對應的應用程序中有一個對應的靜態代碼塊,自動回將驅動的類對象進行驅動加載)
 92             //DriverManager.registerDriver((Driver) Class.forName(driverClass).newInstance());
 93             
 94             conn = DriverManager.getConnection(jdbcUrl,user,password);
 95             
 96         } catch (IOException e) {
 97             // TODO Auto-generated catch block
 98             e.printStackTrace();
 99         }catch (SQLException e) {
100             // TODO Auto-generated catch block
101             e.printStackTrace();
102         }catch (ClassNotFoundException e) {
103             // TODO Auto-generated catch block
104             e.printStackTrace();
105         }
106         return conn;
107     }
108 }

4:用Junit測試實現的JDBC實現數據庫的增刪改查操作:

 1 package com.yinfu.test;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.sql.Connection;
 6 import java.sql.DriverManager;
 7 import java.sql.PreparedStatement;
 8 import java.sql.ResultSet;
 9 import java.sql.SQLException;
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.Properties;
13 
14 import org.junit.Test;
15 
16 import com.yinfu.dao.Employee;
17 import com.yinfu.utils.JDBCUtils;
18 
19 public class JDBCTest {
20 
21     @Test
22     public void testUpdate(){
23         //
24         String sql = "insert into employee (Id,Name,Password) values (1,'wangba',131)";
25         //26         //String sql = "delete from employee where id = 1";
27         //28         //String sql = "update employee set name = 'fuck' where id = 2";
29         //
30         String sqlQuery = "select * from employee";
31         update(sql);
32         testQueryObject(sqlQuery);
33     }
34     
35     public void testQueryObject(String sql){
36         Employee employee = null;
37         List<Employee> list = new ArrayList();
38         Connection conn = null;
39         PreparedStatement ps = null;
40         ResultSet result = null;
41         try {
42             //創建連接
43             conn = JDBCUtils.getConnetions();
44             //創建prepareStatement對象,用於執行SQL
45             ps = conn.prepareStatement(sql);
46             //獲取查詢結果集
47             result = ps.executeQuery();
48             while(result.next()){
49                 employee = new Employee(result.getInt(1),result.getString(2),result.getString(3));
50                 list.add(employee);
51             }
52             System.out.println(list);
53         } catch (Exception e) {
54             e.printStackTrace();
55         }finally{
56             JDBCUtils.release(result, ps, conn);
57         }
58     }
59     
60     public void update(String sql){
61         Connection conn = null;
62         PreparedStatement ps = null;
63         try {
64             //創建數據庫連接
65             conn = JDBCUtils.getConnetions();
66             //創建執行SQL的prepareStatement對象
67             ps = conn.prepareStatement(sql);
68             //用於增刪改操作
69             int result = ps.executeUpdate();
70             System.out.println(result);
71         } catch (Exception e) {
72             System.out.println("出現異常1="+e.toString());
73         }finally{
74             JDBCUtils.release(ps, conn);
75         }
76 
77         
78     }
79 }

Statement 和PrepareStatement的區別:

首先是執行SQL的方法:

statement: 

  Class.forName(jdbcDriver);

  Connection conn = DriverManager.getConnection(jdbcUrl,userName,password);

  String sql = "insert into employee () values ('','','')"

  Statement statement = conn.createStatement();

  statement.executeUpdate(sql);

  其中的SQL語句中若有要動態輸入的數據時,需要用字符串拼接SQL,難以維護容易出錯。

prepareStatement:

  Class.forName(jdbcDriver);

  Connection conn = DriverManager.getConnection(jdbcUrl,userName,password);

  String sql = "insert into employee () values ('','','')"

  PrepareStatement ps = conn.prepareStatement(sql);

  statement.executeUpdate();

  其中的SQL語句中要是有動態輸入的數據時,可以用占位'?'符來代替:

  String sql = "insert into employee () values (?,?,?)";

  然后用prepareStatement接口中的方法來動態賦值:

  ps.setXXX(int paramIndex ,Object value);//參數含義:占位符對應的索引值,該索引值對應的參數值;

 2:(利用反射工具類)升級版查詢:利用反射和JDBC元數據編寫通用的查詢單條記錄方法(ResultSetMetaData是結果集的元數據對象):

1:創建反射工具類:

  1 package com.yinfu.utils;
  2 
  3 import java.lang.reflect.Field;
  4 import java.lang.reflect.InvocationTargetException;
  5 import java.lang.reflect.Method;
  6 import java.lang.reflect.Modifier;
  7 import java.lang.reflect.ParameterizedType;
  8 import java.lang.reflect.Type;
  9 
 10 /**
 11  * 反射的 Utils 函數集合 提供訪問私有變量, 獲取泛型類型 Class, 提取集合中元素屬性等 Utils 函數
 12  * 
 13  * @author Administrator
 14  *
 15  */
 16 public class ReflectionUtils {
 17 
 18     /**
 19      * 通過反射, 獲得定義 Class 時聲明的父類的泛型參數的類型 如: public EmployeeDao extends
 20      * BaseDao<Employee, String>
 21      * 
 22      * @param clazz
 23      * @param index
 24      * @return
 25      */
 26     @SuppressWarnings("unchecked")
 27     public static Class getSuperClassGenricType(Class clazz, int index) {
 28         Type genType = clazz.getGenericSuperclass();
 29 
 30         if (!(genType instanceof ParameterizedType)) {
 31             return Object.class;
 32         }
 33 
 34         Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
 35 
 36         if (index >= params.length || index < 0) {
 37             return Object.class;
 38         }
 39 
 40         if (!(params[index] instanceof Class)) {
 41             return Object.class;
 42         }
 43 
 44         return (Class) params[index];
 45     }
 46 
 47     /**
 48      * 通過反射, 獲得 Class 定義中聲明的父類的泛型參數類型 如: public EmployeeDao extends
 49      * BaseDao<Employee, String>
 50      * 
 51      * @param <T>
 52      * @param clazz
 53      * @return
 54      */
 55     @SuppressWarnings("unchecked")
 56     public static <T> Class<T> getSuperGenericType(Class clazz) {
 57         return getSuperClassGenricType(clazz, 0);
 58     }
 59 
 60     /**
 61      * 循環向上轉型, 獲取對象的 DeclaredMethod
 62      * 
 63      * @param object
 64      * @param methodName
 65      * @param parameterTypes
 66      * @return
 67      */
 68     public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes) {
 69 
 70         for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
 71                 .getSuperclass()) {
 72             try {
 73                 // superClass.getMethod(methodName, parameterTypes);
 74                 return superClass.getDeclaredMethod(methodName, parameterTypes);
 75             } catch (NoSuchMethodException e) {
 76                 // Method 不在當前類定義, 繼續向上轉型
 77             }
 78             // ..
 79         }
 80 
 81         return null;
 82     }
 83 
 84     /**
 85      * 使 filed 變為可訪問
 86      * 
 87      * @param field
 88      */
 89     public static void makeAccessible(Field field) {
 90         if (!Modifier.isPublic(field.getModifiers())) {
 91             field.setAccessible(true);
 92         }
 93     }
 94 
 95     /**
 96      * 循環向上轉型, 獲取對象的 DeclaredField
 97      * 
 98      * @param object
 99      * @param filedName
100      * @return
101      */
102     public static Field getDeclaredField(Object object, String filedName) {
103 
104         for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
105                 .getSuperclass()) {
106             try {
107                 return superClass.getDeclaredField(filedName);
108             } catch (NoSuchFieldException e) {
109                 // Field 不在當前類定義, 繼續向上轉型
110             }
111         }
112         return null;
113     }
114 
115     /**
116      * 直接調用對象方法, 而忽略修飾符(private, protected)
117      * 
118      * @param object
119      * @param methodName
120      * @param parameterTypes
121      * @param parameters
122      * @return
123      * @throws InvocationTargetException
124      * @throws IllegalArgumentException
125      */
126     public static Object invokeMethod(Object object, String methodName, Class<?>[] parameterTypes, Object[] parameters)
127             throws InvocationTargetException {
128 
129         Method method = getDeclaredMethod(object, methodName, parameterTypes);
130 
131         if (method == null) {
132             throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
133         }
134 
135         method.setAccessible(true);
136 
137         try {
138             return method.invoke(object, parameters);
139         } catch (IllegalAccessException e) {
140             System.out.println("不可能拋出的異常");
141         }
142 
143         return null;
144     }
145 
146     /**
147      * 直接設置對象屬性值, 忽略 private/protected 修飾符, 也不經過 setter
148      * 
149      * @param object
150      * @param fieldName
151      * @param value
152      */
153     public static void setFieldValue(Object object, String fieldName, Object value) {
154         Field field = getDeclaredField(object, fieldName);
155 
156         if (field == null)
157             throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
158 
159         makeAccessible(field);
160 
161         try {
162             field.set(object, value);
163         } catch (IllegalAccessException e) {
164             System.out.println("不可能拋出的異常");
165         }
166     }
167 
168     /**
169      * 直接讀取對象的屬性值, 忽略 private/protected 修飾符, 也不經過 getter
170      * 
171      * @param object
172      * @param fieldName
173      * @return
174      */
175     public static Object getFieldValue(Object object, String fieldName) {
176         Field field = getDeclaredField(object, fieldName);
177 
178         if (field == null)
179             throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
180 
181         makeAccessible(field);
182 
183         Object result = null;
184 
185         try {
186             result = field.get(object);
187         } catch (IllegalAccessException e) {
188             System.out.println("不可能拋出的異常");
189         }
190 
191         return result;
192     }
193 }
反射工具類

2:編寫通用查詢:

 1 package com.yinfu.test;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.sql.Connection;
 6 import java.sql.DriverManager;
 7 import java.sql.PreparedStatement;
 8 import java.sql.ResultSet;
 9 import java.sql.ResultSetMetaData;
10 import java.sql.SQLException;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Properties;
16 
17 import org.junit.Test;
18 
19 import com.yinfu.dao.Employee;
20 import com.yinfu.utils.JDBCUtils;
21 import com.yinfu.utils.ReflectionUtils;
22 
23 public class JDBCTest {
24 
25     @Test
26     public void testUpdate(){
27         //
28         String sqlQuery = "select id, name, password from employee where name = ?";
29         Object employee = testQueryObject(Employee.class,sqlQuery,"zhangsan");
30         System.out.println("利用反射="+employee);
31     }
32     
33     public <T> T testQueryObject(Class<T> clazz, String sql, Object ... args){
34         T object = null;
35         Map<String, Object> map = new HashMap<String, Object>();
36         Connection conn = null;
37         PreparedStatement ps = null;
38         ResultSet resultSet = null;
39         try {
40             //創建連接
41             conn = JDBCUtils.getConnetions();
42             //創建prepareStatement對象,用於執行SQL
43             ps = conn.prepareStatement(sql);
44             //將參數賦值到sql的所需參數中
45             for(int i = 0 ; i < args.length ; i++){
46                 ps.setObject(i+1, args[i]);
47             }
48             //一:根據SQL語句和傳入的參數得到結果集,此結果集中全部是純數據值,不帶列名;
49             resultSet = ps.executeQuery();
50             //二:利用ResultSet對象得到ResultSetMetaData對象jdbc的元數據,根據此對象可以知道SQL語句查詢了哪些列,以及列的別名是什么(具體參考JDBC的API進行學習)
51             ResultSetMetaData rsmd = resultSet.getMetaData();
52             while(resultSet.next()){
53                 //把列名的別名和列值分別取出來放到map中作為鍵值出現(resultSet和rsmd結合得到的就是一個表,和數據庫表一樣),由ResultSetMetaData得到每一列的別名,                   //由ResultSet 得到對應的值
54                 for(int i=0;i<rsmd.getColumnCount();i++){
55                     String columnLabel = rsmd.getColumnLabel(i+1);
56                     Object columnValue = resultSet.getObject(columnLabel);
57                     map.put(columnLabel, columnValue);
58                 }
59             }
60             //利用反射創建class對應的對象
61             object = (T) clazz.newInstance();
62             //遍歷map對象,用反射填充對象屬性值
63             for(Map.Entry<String, Object> entry : map.entrySet()){
64                 String fieldName = entry.getKey();
65                 Object fieldValue = entry.getValue();
66                 //利用反射工具類(屬性名對應map的key值,屬性名對應map的value值)
67                 ReflectionUtils.setFieldValue(object, fieldName, fieldValue);
68             }
69         } catch (Exception e) {
70             e.printStackTrace();
71         }finally{
72             JDBCUtils.release(resultSet, ps, conn);
73         }
74         return object;
75     }
76 }

 3:利用BeanUtils工具類實現查詢多條記錄(添加commons-beanutils.jar和commons-logging.jar):

  1 package com.yinfu.test;
  2 
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.sql.Connection;
  6 import java.sql.DriverManager;
  7 import java.sql.PreparedStatement;
  8 import java.sql.ResultSet;
  9 import java.sql.ResultSetMetaData;
 10 import java.sql.SQLException;
 11 import java.util.ArrayList;
 12 import java.util.HashMap;
 13 import java.util.List;
 14 import java.util.Map;
 15 import java.util.Properties;
 16 
 17 import org.apache.commons.beanutils.BeanUtils;
 18 import org.junit.Test;
 19 
 20 import com.yinfu.dao.Employee;
 21 import com.yinfu.utils.JDBCUtils;
 22 import com.yinfu.utils.ReflectionUtils;
 23 
 24 public class JDBCTest {
 25 
 26     @Test
 27     public void testUpdate(){
 28         //查多條
 29         String sqlQueryList = "select id, name, password from employee";
 30         List<Employee> testQueryList = testQueryList(Employee.class,sqlQueryList);
 31         System.out.println("查詢多條:"+testQueryList);
 32         
 33     }
 34     
 35      //查詢多條記錄
 36     public <T> List<T> testQueryList(Class<T> clazz, String sql, Object ...args ){
 37         //用於接收返回值
 38         T object = null;
 39         List<T> list = new ArrayList<>();
 40         Connection conn = null;
 41         PreparedStatement rs = null;
 42         ResultSet resultSet = null;
 43         try {
 44             //獲取數據庫連接
 45             conn = JDBCUtils.getConnetions();
 46             rs = conn.prepareStatement(sql);
 47             //填充占位符
 48             for(int i = 0; i < args.length; i++){
 49                 rs.setObject(i+1, args[i]);
 50             }
 51             //獲取結果集
 52             resultSet = rs.executeQuery();
 53             //1:准備一個List<Map<String, Object>>集合,其中key為列名,value為列值,每一個map對應一條記錄
 54             List<Map<String, Object>> listMap = new ArrayList<>();
 55             //2:得到jdbc的元數據
 56             ResultSetMetaData rsmd = rs.getMetaData();
 57             while(resultSet.next()){
 58                 Map<String, Object> map = new HashMap<>();
 59                 for(int i = 0; i < rsmd.getColumnCount(); i++){
 60                     //游標是從1開始的
 61                     String columnLabel = rsmd.getColumnLabel(i+1);
 62                     Object columnValue = resultSet.getObject(columnLabel);
 63                     map.put(columnLabel, columnValue);
 64                 }
 65                 //3:把一條記錄map放入到listMap中
 66                 listMap.add(map);
 67             }
 68             
 69             /*//上面一段代碼可以這樣寫
 70             List<String> labelList = getColumnLabels(resultSet);
 71             while(resultSet.next()){
 72                 Map<String, Object> map = new HashMap<>();
 73                 for(String columnLabel : labelList){
 74                     Object columnValue = resultSet.getObject(columnLabel);
 75                     map.put(columnLabel, columnValue);
 76                 }
 77                 //3:把一條記錄map放入到listMap中
 78                 listMap.add(map);
 79             }*/
 80             
 81             //4:遍歷listMap集合,把其中的每一個map都轉換成對應的Class對象,並放到list中進行返回
 82             if(listMap.size()>0){
 83                 for(Map<String, Object> mapObj : listMap){
 84                     //有記錄就通過反射得到對應的類對象
 85                     object = clazz.newInstance();
 86                     for(Map.Entry<String, Object> entry : mapObj.entrySet()){
 87                         String propertyName = entry.getKey();
 88                         Object propertyValue = entry.getValue();
 89                         //利用工具類beanutils進行實體類轉換
 90                         BeanUtils.setProperty(object, propertyName, propertyValue);
 91                     }
 92                     list.add(object);
 93                 }
 94             }
 95             
 96         } catch (Exception e) {
 97             e.printStackTrace();
 98         }
 99         
100         return list;
101     }
102     
103     private List<String> getColumnLabels(ResultSet resultSet) throws SQLException{
104         ResultSetMetaData rsmd = resultSet.getMetaData();
105         List<String> list = new ArrayList<>();
106         for(int i = 0; i<rsmd.getColumnCount(); i++){
107             list.add(rsmd.getColumnLabel(i+1));
108         }
109         return list;
110     }
111 }
查詢多條記錄

 4:可以用獲取PrepareStatement的另一個重載方法得到,然后再用此對象的getGeneratedKeys()方法得到插入的數據時自動生成的ID的結果集,此結果集就一列,列名為:GENERATED_K。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM