手动封装JDBC的底层实现

1.JDBC介绍

1.什么是JDBC?
JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库。原来我们操作数据库是在控制台使用SQL语句来操作数据库,JDBC是用Java语言向数据库发送SQL语句。
对于初学者刚开始用java操作数据库时,我们在进行数据库的增删改查时,每一个方法都需要重复的connection去连接数据库进行操作,然后用完后进行关流操作,这对于我们程序员来说重复写同样的代码工作效率会降低,JDBC简单点说就是一款方便操作数据库操作的一款小工具,当我们使用增删改查时,只需要调里面对应的方法即可。
2 JDBC原理
JDBC是Sun公司制定的一个可以用Java语言连接数据库的技术。
是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC为数据库开发人员提供了一个标准的API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯 Java API 编写数据库应用程序,并且可跨平台运行,并且不受数据库供应商的限制。

2.JDBC实现步骤

1.工程结构
创建一个java工程,until包下放两个类,JDBCTools里面放连接和关流的方法,MyJDBCUntil里面写增删改查的方法,db.properties写数据库的连接地址,端口号,用户名,密码,lib里面放我们需要导入的connector.jar包
在这里插入图片描述
2.properties里面的日志信息
在这里插入图片描述
3.1JDBCTools

	public static Connection getConnection() {
   	// 1.读配置文件参数
   	Properties properties = new Properties();
   	Connection conn = null;
   	try {
   		InputStream in = JDBCTools.class.getClassLoader().getResourceAsStream("db.properties");
   		properties.load(in);
   		String user = properties.getProperty("user");
   		String password = properties.getProperty("password");
   		String url = properties.getProperty("url");
   		String dirver = properties.getProperty("driver");
   		//通过反射获取dirver驱动加载
   		Class.forName(dirver);
   		conn = DriverManager.getConnection(url, user, password);
   	} catch (FileNotFoundException e) {
   		e.printStackTrace();
   	} catch (IOException e) {
   		e.printStackTrace();
   	} catch (ClassNotFoundException e) {
   		e.printStackTrace();
   	} catch (SQLException e) {
   		e.printStackTrace();
   	}

   	return conn;
   }

3.2关流操作

/**
    * 关闭连接
    * 
    * @param rs
    * @param ps
    * @param connection
    */
   public static void close(ResultSet rs, PreparedStatement ps, Connection connection) {
   	try {
   		if (rs != null) {
   			rs.close();
   		}
   		if (ps != null) {
   			ps.close();
   		}
   		if (connection != null) {
   			connection.close();
   		}
   	} catch (SQLException e) {
   		e.printStackTrace();
   	}
   }

3.3方法的重载关流,调用的方法不同所关闭的流也不同,所以我们进行重载就行

	public static void close(PreparedStatement ps, Connection connection) {
   	close(null, ps, connection);
   }

   public static void close(Connection connection) {
   	close(null, null, connection);
   }

   public static void main(String[] args) {
   	JDBCTools.getConnection();
   }

4.MyJDBCUntil
4.1 更新数据的方法

	/**
    * 数据库的更新操作,包括增加,修改,删除不包括查询
    * @param sql
    * @param params 这里用的动态数组  ...表示动态数组,即可以传入多个参数,有动态数组传参必须放在最后
    * @return 返回受影响行数
    */
   public static int executeUpdate(String sql,Object...params) {
   	//获取连接
   	Connection conn=JDBCTools.getConnection();
   	PreparedStatement ps = null;
   	int id = -1;
   	try {
   		ps = conn.prepareStatement(sql);
   		if (params != null) {
   			for (int i = 1; i <= params.length; i++) {
   				ps.setObject(i, params[i - 1]);
   			}
   		}
   		id = ps.executeUpdate();
   	} catch (SQLException e) {
   		e.printStackTrace();
   	}
   	return id;
   }

4.2查询


   /**
    * String sql = "SELECT number,username,age FROM student WHERE number = ?";
    * 
    * @param sql
    * @param params Class<T> cla 类类型 查询返回对象的类型,如查询Student对象,cla:学生类类型 Student.class
    * @return
    */
   public static <T> T executeQueryObj(Class<T> cla, String sql, Map<String, String> columParams, Object... params) {
   	Connection conn = JDBCTools.getConnection();
   	PreparedStatement ps = null;
   	ResultSet rs = null;
   	T obj = null; // 查询返回的对象
   	try {
   		ps = conn.prepareStatement(sql);
   		// 设置参数
   		if (params != null) {
   			for (int i = 1; i <= params.length; i++) {
   				ps.setObject(i, params[i - 1]);
   			}
   		}
   		rs = ps.executeQuery();
   		// 处理查询结果集
   		ResultSetMetaData rsmd = rs.getMetaData(); // 返回结果集元数据
   		int count = rsmd.getColumnCount(); // 返回字段个数
   		if (rs.next()) {
   			Map<String, Object> columMap = new HashMap<String, Object>();
   			obj = cla.newInstance(); // new Student() //通过反射实例化对象时一定要有默认构造方法
   			for (int k = 0; k < count; k++) {
   				String columLable = rsmd.getColumnLabel(k + 1); // 字段名称 number,username,password
   				Object columValue = rs.getObject(columLable); // 字段值 1001 admin 123456
   				columMap.put(columLable, columValue);
   			}
   			Set<String> keySets = columMap.keySet();
   			for (String key : keySets) {
   				if (columParams == null) {
   					BeanUtils.setProperty(obj, key, columMap.get(key));
   				} else {
   					BeanUtils.setProperty(obj, getPropertyByKey(columParams, key), columMap.get(key));
   				}
   			}

   		}
   	} catch (SQLException e) {
   		e.printStackTrace();
   	} catch (InstantiationException e) {
   		e.printStackTrace();
   	} catch (IllegalAccessException e) {
   		e.printStackTrace();
   	} finally {
   		JDBCTools.close(rs, ps, conn);
   	}
   	return obj;
   }

注:上面的beanutil是一个依赖包,需要导入
属性名与字段名不同的查询

	/**
    * 属性名与字段名不一样 Object... 可变数组 {1,2} {1,2,3,4} Object[] obj = new Object[3]
    */
   public static <T> List<T> executeQueryList(Class<T> clazz, String sql, Map<String, String> parameterMap,
   		Object... args) {
   	List<T> list = new ArrayList<>();
   	Connection conn = JDBCTools.getConnection();
   	PreparedStatement pstmt = null;
   	ResultSet rs = null;
   	try {
   		pstmt = conn.prepareStatement(sql);
   		if (args != null) {
   			for (int i = 0; i < args.length; i++) {
   				pstmt.setObject(i + 1, args[i]);
   			}
   		}
   		rs = pstmt.executeQuery();
   		// 1.通过SQL语句得到查询了多少列
   		ResultSetMetaData rsmd = rs.getMetaData();
   		// Map<String, Object> map = new HashMap<>();
   		List<Map<String, Object>> values = new ArrayList<>();
   		Map<String, Object> map = null;
   		while (rs.next()) {
   			map = new HashMap<>();
   			// 通过反射获取对象的实例
   			for (int i = 0; i < rsmd.getColumnCount(); i++) {
   				// 2.哪些列
   				String columnLabel = rsmd.getColumnLabel(i + 1);
   				// 3.每一列对应的值是什么
   				Object value = rs.getObject(i + 1);
   				// System.out.println(columnLabel+"------"+value);
   				map.put(columnLabel, value);
   			}
   			values.add(map);
   		}
   		T entity = null;
   		// 4.将值赋给对象的属性
   		if (values.size() > 0) {
   			if (parameterMap == null) { // 字段名称和属性相同情况
   				for (int i = 0; i < values.size(); i++) {
   					entity = clazz.newInstance();// 通过反射实例化对象
   					for (String key : values.get(i).keySet()) {
   						BeanUtils.setProperty(entity, key, values.get(i).get(key));
   					}
   					list.add(entity);
   				}
   			} else {
   				for (int i = 0; i < values.size(); i++) {
   					entity = clazz.newInstance();// 通过反射实例化对象
   					for (String key : values.get(i).keySet()) {
   						BeanUtils.setProperty(entity, getPropertyByKey(parameterMap, key), values.get(i).get(key));
   					}
   					list.add(entity);
   				}
   			}
   		}
   	} catch (SQLException e) {
   		e.printStackTrace();
   	} catch (InstantiationException e) {
   		e.printStackTrace();
   	} catch (IllegalAccessException e) {
   		e.printStackTrace();
   	} catch (InvocationTargetException e) {
   		e.printStackTrace();
   	}
   	return list;
   }

   /**
    * 
    * @param columParams 字段与属性映射 columParams.put("username", "userName");
    * @param field       字段名
    * @return 对象属性名
    */
   public static String getPropertyByKey(Map<String, String> columParamsMap, String field) {
   	for (String key : columParamsMap.keySet()) {
   		if (field.equals(key)) {
   			return columParamsMap.get(key);
   		}
   	}
   	return field;
   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值