zoukankan      html  css  js  c++  java
  • 用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。

  • 相关阅读:
    go语言判断末尾不同的长字符串的方法
    Go语言高级特性总结——Struct、Map与JSON之间的转化
    MacOS使用常用配置
    关于联盟链的一种激励扩张思路(原创)
    密码学中经典算法及应用
    无线网络
    基础的并查集
    找单词
    找零钱
    最大子矩阵
  • 原文地址:https://www.cnblogs.com/lubolin/p/7701387.html
Copyright © 2011-2022 走看看