随着shh2框架各种操作的便利性,越来越多的Java WEB开发人员选择通过加入这些框架以提高开发效率,但是,如果在不了解这些框架使用的场合的情况下,一拿到项目就盲目地选择这些框架进行系统架构的搭建,就有可能造成很多没必要的资源浪费。
在项目开发中,对数据库的CRUD操作我们一般都是无法避免的操作,虽然hibernate封装的很完美,但是,由于本人对这个框架的底层原理不是很了解,每次使用的时候心里总觉得没底,代码一旦出现异常,很多时候都没法快速有效地解决,因此,为了让代码异常处理风险控制在自己的可控范围内,还是决定先将数据的CRUD持久化操作(DAO)用自己的方式通过JDBC进行一次封装,以便更好地管理自己的代码。关于Hibernate框架的使用,还是先弄懂它的一些底层实现原理后,再根据项目的需要酌情选择使用。
下面具体讲讲通过我自己的方式对有关DAO层数据库基本CRUD操作的Java实现(此处已MySQL为例,其他数据库只需做部分修改即可)。
备注:若要试用本示例,只需按照给出的顺序依次复制代码建立相应的类即可。另外,在项目lib目录下加入mysql链接jar包。
(1)定义数据源常量类
- package com.jkitn.jkits.common;
- /**
- * 定义数据源常量类
- * @author xdweleven
- * @version 1.0
- */
- public class JdbcConfig {
- /** 数据库驱动 */
- public static final String DRIVERCLASSNAME = "com.mysql.jdbc.Driver";
- /** 数据库URL */
- public static final String URL = "jdbc:mysql://localhost:3306/app_jkit";
- /** 数据库用户名 */
- public static final String USERNAME = "root";
- /** 数据库密码 */
- public static final String PASSWORD = "root";
- }
(2)定义结果集(ResultSet)到pojo对象的映射
- package com.jkitn.jkits.dao.common;
- import java.lang.reflect.Field;
- import java.sql.ResultSet;
- import java.sql.ResultSetMetaData;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * 说明:实现结果集到pojo对象的映射
- * @author xdweleven
- * @version 1.0
- */
- public class RowMapper<T>{
- private Class<T> objectClass;
- public RowMapper(Class<T> objectClass) {
- this.objectClass = objectClass;
- }
- /**
- * 实现单条记录到对象的映射
- * @param rs 结果集
- * @param rowNum 当前行数
- * @return
- * @throws SQLException
- */
- public T mapRow(ResultSet rs, int rowNum) throws SQLException {
- try {
- T object = objectClass.newInstance();
- // 得到结果集的字段集合
- ResultSetMetaData metaData = rs.getMetaData();
- int columnNum = metaData.getColumnCount();
- Field[] fields = object.getClass().getDeclaredFields();
- // 设置对象属性的值,若不存在,则设置为null.
- for (int i = 0; i < fields.length; i++) {
- Field field = fields[i];
- int flag = 0;
- for (int j = 1; j <= columnNum; j++) {
- if (metaData.getColumnName(j).toLowerCase().equals(field.getName().toLowerCase())) {
- flag = 1;
- break;
- }
- }
- field.setAccessible(true);
- if (flag == 1) {
- this.typeMapper(field, object, rs);
- }else {
- field.set(object, null);
- }
- field.setAccessible(false);
- }
- return object;
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 实现多条记录到结果集的映射
- * @param rs
- * @return
- */
- public List<T> mapRows(ResultSet rs){
- int rowNum = 0;
- List<T> objList = new ArrayList<T>();
- try {
- while(rs.next()){
- objList.add(this.mapRow(rs, rowNum++));
- }
- rs.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return objList;
- }
- /**
- * 类型的映射
- * @param field
- * @param obj
- * @param rs
- * @throws IllegalArgumentException
- * @throws IllegalAccessException
- * @throws SQLException
- */
- private void typeMapper(Field field, Object obj, ResultSet rs) {
- String typeName = field.getType().getName(); // 得到字段类型
- try {
- if (typeName.equals("java.lang.String")) {
- field.set(obj, rs.getString(field.getName()));
- } else if (typeName.equals("int")
- || typeName.equals("java.lang.Integer")) {
- field.set(obj, rs.getInt(field.getName()));
- } else if (typeName.equals("long")
- || typeName.equals("java.lang.Long")) {
- field.set(obj, rs.getLong(field.getName()));
- } else if (typeName.equals("float")
- || typeName.equals("java.lang.Float")) {
- field.set(obj, rs.getFloat(field.getName()));
- } else if (typeName.equals("double")
- || typeName.equals("java.lang.Double")) {
- field.set(obj, rs.getDouble(field.getName()));
- } else if (typeName.equals("boolean")
- || typeName.equals("java.lang.Boolean")) {
- field.set(obj, rs.getBoolean(field.getName()));
- } else if (typeName.equals("java.util.Date")) {
- field.set(obj, rs.getTimestamp(field.getName()));
- } else {
- }
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- package com.jkitn.jkits.common;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.List;
- import com.jkitn.jkits.dao.common.RowMapper;
- /**
- * 定义数据库连接辅助类DBConn
- * @author xdweleven
- * @version 1.0
- */
- public class DBConn {
- private Connection conn = null;
- private PreparedStatement pstmt = null;
- private ResultSet rs = null;
- /**
- * 创建数据库的连接
- * @return 返回数据库连接对象
- */
- public Connection getConn(){
- try {
- // 加载数据库驱动
- Class.forName(JdbcConfig.DRIVERCLASSNAME);
- // 创建Connection接口对象,用于获取MySQL数据库的连接对象
- conn = DriverManager.getConnection(JdbcConfig.URL, JdbcConfig.USERNAME, JdbcConfig.PASSWORD);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return conn;
- }
- /**
- * 更新数据库操作(包括增删改操作)
- * @param sql 待执行sql语句
- * @param objs 用于设置预编译语句中带入的参数
- * @return null
- * @throws Exception
- */
- public int execUpdate(String sql, Object ...objs) throws Exception{
- // 获取预编译环境
- pstmt = this.getConn().prepareStatement(sql);
- if(objs != null && objs.length > 0){
- for(int i = 0; i < objs.length; i++){
- pstmt.setObject(i+1, objs[i]);
- }
- }
- // 执行更新语句
- int result = pstmt.executeUpdate();
- // 断开连接,释放资源
- this.close(rs, pstmt, conn);
- return result;
- }
- /**
- * 数据库查询操作
- * @param sql 待执行sql语句
- * @param objs 用于设置预编译语句中带入的参数
- * @return 类T的List数据类型,即返回查询到的所有数据信息
- * @throws Exception
- */
- public <T> List<T> execQuery(String sql, RowMapper<T> mapper, Object ...objs) throws Exception{
- // 获取预编译环境
- pstmt = this.getConn().prepareStatement(sql);
- if(objs != null && objs.length > 0){
- for(int i = 0; i < objs.length; i++){
- pstmt.setObject(i+1, objs[i]);
- }