JDBC工具类的两种写法

​​​​小配置文件:jdbc.properties

driverClass=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
username=hr
password=hr

1.工具类只提供Connection对象静态方法和释放资源静态方法

工具类:JDBCUtil 

package com.zp.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class JDBCUtil {
    private static DataSource dataSource ;
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<> ();

    static {
        InputStream is = JDBCUtil.class.getResourceAsStream ("/jdbc.properties");
        Properties prop = new Properties ();
        try {
            prop.load (is);
            dataSource = DruidDataSourceFactory.createDataSource (prop);
            is.close ();
        } catch (Exception e) {
            e.printStackTrace ();
        }
    }

    public static Connection getConnection(){
        Connection conn = threadLocal.get ();
        if(conn == null){
            try {
                conn = dataSource.getConnection ();
                threadLocal.set (conn);
            } catch (SQLException e) {
                e.printStackTrace ();
            }
        }
        return conn;
    }

    public static void close(Connection conn, PreparedStatement ps, ResultSet rs){
        try {
            if(rs != null){
                rs.close ();
            }
            if(ps != null){
                ps.close ();
            }
            if(conn != null){
                conn.close ();   //把conn对象返回给连接池中  没有关闭连接
                threadLocal.remove ();  //移除当前线程绑定的连接对象,怕其它人使用该线程,但该线程绑定的conn对象已经返回给连接池了   java.sql.SQLException: connection holder is null
            }
        }catch (Exception e){
            e.printStackTrace ();
        }
    }

    public static void main(String[] args) throws SQLException {
        Connection conn = getConnection ();
        System.out.println (conn);
//        conn.close (); //这里关  // conn: oracle.jdbc.driver.T4CConnection@573fd745
                           //conn2:oracle.jdbc.driver.T4CConnection@573fd745     获取的是同一个(只有多线程的时候才可能获取两个不同的)

        Connection conn2 = getConnection ();
        System.out.println (conn2);
        conn.close ();  //conn:oracle.jdbc.driver.T4CConnection@573fd745
                        //conn2:oracle.jdbc.driver.T4CConnection@15327b79
        conn2.close ();



    }
}

2.工具类提供Connection对象静态方法和释放资源静态方法并且封装增删改查

       2.1通过接口回调封装查询

  RowMapper接口

package com.zp.util;

import java.sql.ResultSet;
import java.sql.SQLException;

public interface RowMapper<T> {
    public T row(ResultSet rs) throws SQLException;
}

谁调用查询谁实现这接口,并传递实现类

dao接口实现类:

package com.zp.dao.impl;

import com.zp.dao.ProductDAO;
import com.zp.entity.Product;
import com.zp.util.RowMapper;
import com.zp.util.JDBCUtil;
import com.zp.util.JDBCUtil2;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class ProductDAOImpl2 implements ProductDAO {
    @Override
    public void insert(Product product) {
        JDBCUtil2.executeUpdate ("insert into t_product values(seq_product.nextval,?,?,?)",product.getPname (),product.getPrice (),product.getDescr ());
    }

    @Override
    public void delete(int pid) {
        JDBCUtil2.executeUpdate ("delete from t_product where pid = ?",pid);
    }

    @Override
    public void update(Product product) {
        JDBCUtil2.executeUpdate ("update t_product set pname = ? , price = ? , descr = ? where pid = ?",product.getPname (),product.getPrice (),product.getDescr (),product.getPid ());
    }

    @Override
    public List<Product> selectAll() {
        List<Product> list = JDBCUtil2.selectAll ("select * from t_product", new RowMapper<Product> () {

            @Override
            public Product row(ResultSet rs) throws SQLException {
                Product product = new Product (rs.getInt ("pid"), rs.getString ("pname"), rs.getDouble ("price"), rs.getString ("descr"));
                return product;
            }
        });
        return list;
    }

    @Override
    public Product selectById(int pid) {
        Product product = JDBCUtil2.selectOne ("select * from t_product where pid = ?", new RowMapper<Product> () {
            @Override
            public Product row(ResultSet rs) throws SQLException {
                Product product = new Product (rs.getInt ("pid"), rs.getString ("pname"), rs.getDouble ("price"), rs.getString ("descr"));
                return product;
            }
        }, pid);
        return product;
    }
}

工具类:JDBCUtil2.class

package com.zp.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 封装增删改查方法
 * 使用接口回调封装查询
 */
public class JDBCUtil2 {
    private static DataSource dataSource;
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<> ();

    static {
        InputStream is = JDBCUtil2.class.getResourceAsStream ("/jdbc.properties");
        Properties prop = new Properties ();
        try {
            prop.load (is);
            dataSource = DruidDataSourceFactory.createDataSource (prop);
            is.close ();
        } catch (Exception e) {
            e.printStackTrace ();
        }
    }

    public static Connection getConnection(){
        Connection conn = threadLocal.get ();
        if (conn == null){
            try {
                conn = dataSource.getConnection ();
                threadLocal.set (conn);
            } catch (SQLException e) {
                e.printStackTrace ();
            }
        }
        return conn;
    }

    //封装增删改操作
    public static void executeUpdate(String sql,Object... objects){
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = getConnection ();
            ps = conn.prepareStatement (sql);
            if (objects!=null && objects.length>0){
                for (int i = 0; i < objects.length; i++) {
                    ps.setObject (i+1,objects[i]);
                }
            }
            ps.executeUpdate ();
        }catch (Exception e){
            e.printStackTrace ();
            throw new RuntimeException (e);
        }finally {
            close (null,ps,null);
        }
    }

    //封装查询  使用接口回调
    public static <T> List<T> selectAll(String sql, RowMapper<T> rowMapper,Object... objects){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<T> list = new ArrayList<> ();
        try {
            conn = getConnection ();
            ps = conn.prepareStatement (sql);
            if(objects!=null && objects.length>0){
                for (int i = 0; i < objects.length; i++) {
                    ps.setObject (i+1,objects[i]);
                }
            }
            rs = ps.executeQuery ();
            while (rs.next ()){
                //list.add (new Product (rs.getInt ("pid"),rs.getString ("pname"),rs.getDouble ("price"),rs.getString ("descr")));
                // 不具有通用性,要想具有通用性,就让谁调用谁提供里面的这行封装代码,创建一个接口(RowMapper),
                // 这个接口有一个row方法,谁调用谁实现,实现体包含实体类的封装,返回封装好的对象
                list.add (rowMapper.row (rs));
            }
        }catch (Exception e){
            e.printStackTrace ();
            throw new RuntimeException (e);
        }finally {
            close (null,ps,rs);
        }
        return list;
    }

    //封装查询一个  使用接口回调
    public static <T> T selectOne(String sql, RowMapper<T> rowMapper,Object... objects){
        List<T> list = selectAll (sql, rowMapper, objects);
        return list!=null?list.get (0):null;
    }

    public static void close(Connection conn, PreparedStatement ps, ResultSet rs){
        try {
            if (rs != null){
                rs.close ();
            }
            if(ps != null){
                ps.close ();
            }
            if(conn != null){
                conn.close ();
                threadLocal.remove ();
            }
        }catch (Exception e){
            e.printStackTrace ();
        }
    }
}

      2.1通过反射实现查询

   查询方法传递实体类的类对象

 @Override
    public List<Product> selectAll() {
        List<Product> list = JDBCUtil3.selectAll ("select * from t_product", Product.class);
        return list;
    }

查询封装方法

//封装查询  使用反射
    public static <T> List<T> selectAll(String sql, Class<T> clazz, Object... objects) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<T> list = new ArrayList<> ();
        try {
            conn = getConnection ();
            ps = conn.prepareStatement (sql);
            if (objects != null && objects.length > 0) {
                for (int i = 0; i < objects.length; i++) {
                    ps.setObject (i + 1, objects[i]);
                }
            }
            rs = ps.executeQuery ();

            ResultSetMetaData metaData = rs.getMetaData ();   //getMetaData方法作用:获取查询结果集的的元数据(包含了所有的列)
            int count = metaData.getColumnCount ();   //getColumnCount方法作用:获取查询结果列的总个数
//            System.out.println (count);

            T t = null;

            while (rs.next ()) {
                t = clazz.newInstance ();  //反射创建对象   一个对象代表一行数据

                for (int i = 1; i <= count; i++) {
                    String columnName = metaData.getColumnName (i);   //获取列名
                    Object value = rs.getObject (columnName);    //根据列名获取对应列的值


                    if (value == null){
                        continue;
                    }
//                    System.out.println (columnName);  //获取列名
//                    System.out.println (value);
                    columnName = "set" + columnName.substring (0, 1).toUpperCase () + columnName.substring (1).toLowerCase ();
                    //            "set"   +  "P"  +  "name"     setPname
//                    System.out.println (columnName);


                    //将每一列的值赋值给t对象中的属性  --->   要求:表中的列名和实体类属性名必须一致
                    Method[] methods = clazz.getMethods ();   //获取当前传递过来实体类中所有的方法
                    for (Method method : methods) {
                        /*
                            java.lang.IllegalArgumentException: argument type mismatch
                            出现该异常原因:rs.getObject (columnName)获取oracle中的number类型时Object对应着
                            java中的java.math.BigDecimal类型(运行时的Object就是java.math.BigDecimal类型)
                            此类型不能自动装换为int或者double
                        */
                        if (method.getName ().equals (columnName)) {
                            if (value instanceof BigDecimal) {
                                Class type = method.getParameterTypes ()[0];
                                if (type.getName ().equals ("int")){
                                    value = ((BigDecimal)value).intValue ();
                                }
                                if (type.getName ().equals ("double")){
                                    value = ((BigDecimal)value).doubleValue ();
                                }
                            }
                            method.invoke (t, value);  //java.lang.IllegalArgumentException  数据库number类型的值为空时执行该方法会报该异常
                            break;
                        }
                    }
                }


                list.add (t);
            }
        } catch (Exception e) {
            e.printStackTrace ();
            throw new RuntimeException (e);
        } finally {
            close (null, ps, rs);
        }
        return list;
    }

 

 

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值