JAVA实现DAO基本层CRUD操作

2022-07-05 21:32:42 浏览数 (1)

大家好,又见面了,我是全栈君

随着shh2各种操作方便框架。越来越多JAVA WEB效率,可是,假设在不了解这些框架使用的场合的情况下,一拿到项目就盲目地选择这些框架进行系统架构的搭建,就有可能造成非常多不是必需的资源浪费。

在项目开发中。对数据库的CRUD操作我们一般都是无法避免的操作,尽管hibernate封装的非常完美,可是。因为本人对这个框架的底层原理不是非常了解,每次使用的时候心里总认为没底。代码一旦出现异常,非常多时候都没法高速有效地解决。因此,为了让代码异常处理风险控制在自己的可控范围内,还是决定先将数据的CRUD持久化操作(DAO)用自己的方式通过JDBC进行一次封装,以便更好地管理自己的代码。

关于Hibernate框架的使用,还是先弄懂它的一些底层实现原理后。再依据项目的须要酌情选择使用。

以下详细讲讲通过我自己的方式对有关DAO层数据库基本CRUD操作的JAVA实现(此处已MySQL为例,其它数据库仅仅需做部分改动就可以)。

备注:若要试用本演示样例,仅仅需依照给出的顺序依次复制代码建立对应的类就可以。另外。在项目lib文件夹下增加mysql链接jar包。

(1)定义数据源常量类

代码语言:javascript复制
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";
	 /** 数据库username */
	 public static final String USERNAME = "root";
	 /** 数据库password */
	 public static final String PASSWORD = "root";
}

(2)定义结果集(ResultSet)到pojo对象的映射

代码语言:javascript复制
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();
		}
	}
}

(3)定义数据库连接辅助类DBConn

代码语言:javascript复制
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]);
			}
		}
		// 运行更新语句
		rs = pstmt.executeQuery();
		// 运行关系到对象的映射
		List<T> result = mapper.mapRows(rs);
		// 断开连接。释放资源
		this.close(rs, pstmt, conn);
		return result;
	}	
	
	/**
	 * 运行运行的SQL语句并返回结果集
	 * @param sql SQL语句
	 * @param params 參数
	 * @return 返回结果集
	 */
	public ResultSet queryForResultSet(String sql, Object... objs) throws Exception{
		// 获取预编译环境
		pstmt = conn.prepareStatement(sql);
		if(objs != null && objs.length > 0){
			for(int i = 0; i < objs.length; i  ){
				pstmt.setObject(i 1, objs[i]);
			}
		}
		// 运行更新语句
		rs = pstmt.executeQuery();
		// 断开连接,释放资源
		this.close(null, pstmt, conn);
		return rs;
	}
	
	/**
	 * 关闭数据库连接,释放所占的系统资源
	 * @param rs结果集、ppst预编译命令、conn数据库
	 * @return null
	 * @throws Exception 
	 */
	public void close(ResultSet rs, PreparedStatement ppst, Connection conn) throws Exception{
		if(rs != null){
			rs.close();
		}
		if(ppst != null){ 
			ppst.close();
		}
		if(conn != null){
			conn.close();
		}
	}
}

(4)定义通用分页查询实体类

代码语言:javascript复制
package com.jkitn.jkits.common;

import java.util.List;

/**
 * 说明:实现通用分页查询实体类
 * @author xdweleven
 * @version 1.0
 */
public class PageBean<T> {
	private int totalRows; // 总记录数
	private int totalPages; // 总页数
	private int curPage; // 当前页码
	private int prePage; // 上一页页码
	private int nextPage; // 下一页页码
	private int rowsPerPage; // 每页显示的记录数 
	private List<T> pageList; // 当前页的数据集
	
    /**
     * 初始化分页bean对象
     * @param totalRows 总记录数
     * @param rowsPerPage 每页显示的记录数
     */
	public void initPageBean(int totalRows, int rowsPerPage){
		this.rowsPerPage = rowsPerPage;
		this.totalRows = totalRows;
		this.totalPages = (this.totalRows-1)/this.rowsPerPage   1;
		// 设置上一页
		if(this.curPage == 1){
			this.setPrePage(1);
		}else{
			this.setPrePage(this.curPage-1);
		}
		// 设置下一页
		if(this.curPage == this.totalPages){
			this.setNextPage(this.totalPages);
		}else{
			this.setNextPage(this.curPage   1);
		}
	}
	
	/**
	 * 生成SQLServer的分页查询语句
	 * @param sql 原始sql语句
	 * @param curPage 第几页
	 * @param rowsPerPage 每页多少行 
	 */
	public String getPageSQLServer(String sql, int curPage, int rowsPerPage){
		String afterFrom = sql.toLowerCase().substring(sql.indexOf("from"));
		String pageSql = null;
		if(afterFrom.indexOf("where") == -1){
			 pageSql = "select top "  rowsPerPage   " * " afterFrom
			 " where id not in(select top " rowsPerPage*(curPage-1) " id "
			 afterFrom " order by id desc)" "order by id desc";
		}else{
			pageSql = "select top "  rowsPerPage   " * " afterFrom
			 " and id not in(select top " rowsPerPage*(curPage-1) " id "
			 afterFrom " order by id desc)" "order by id desc";
		}
		return pageSql;
	}
	
	/**
	 * 生成MySql分页sql语句
	 * @param sql 原始sql语句
	 * @param curPage 第几页
	 * @param rowsPerPage 每页多少行 
	 * @return 返回分页SQL语句
	 */
	public String getPageMySQL(String sql, int curPage, int rowsPerPage){
		String pageSql = sql " limit "  (curPage-1)*rowsPerPage "," rowsPerPage;
		return pageSql;
	}
	
	/**
	 * 生成Oracle分页查询语句
	 * @param sql 原始sql语句
	 * @return 返回分页SQL语句
	 */
	public String getOrclPageSql(String sql){
		int begin = (curPage - 1) * rowsPerPage;
		int end = begin   rowsPerPage;
		StringBuffer pagingSelect = new StringBuffer(300);
		pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
		pagingSelect.append(sql);
		pagingSelect.append(" ) row_ where rownum <= " end ") where rownum_ > " begin);
		return pagingSelect.toString();
	}
	
	public List<T> getPageList() {
		return pageList;
	}

	public void setPageList(List<T> pageList) {
		this.pageList = pageList;
	}
	public int getTotalRows() {
		return totalRows;
	}

	public void setTotalRows(int totalRows) {
		this.totalRows = totalRows;
	}

	public int getTotalPages() {
		return totalPages;
	}

	public void setTotalPages(int totalPages) {
		this.totalPages = totalPages;
	}

	public int getCurPage() {
		return curPage;
	}

	public void setCurPage(int curPage) {
		this.curPage = curPage;
	}

	public int getPrePage() {
		return prePage;
	}

	public void setPrePage(int prePage) {
		this.prePage = prePage;
	}

	public int getNextPage() {
		return nextPage;
	}

	public void setNextPage(int nextPage) {
		this.nextPage = nextPage;
	}

	public int getRowsPerPage() {
		return rowsPerPage;
	}

	public void setRowsPerPage(int rowsPerPage) {
		this.rowsPerPage = rowsPerPage;
	}
}

(5)定义SQL语句的经常用法工具类

代码语言:javascript复制
package com.jkitn.jkits.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 说明:自己主动生成对象的增删改查SQL语句的通用方法工具类
 * @author xdweleven
 * @version 1.0 
 */
public class SQLUtil {	
	/**
	 * 自己主动生成插入指定对象的SQL语句,不包括对象属性的值为空的字段
	 * @param obj 待生成插入SQL语句的对象
	 * @param tableName 待插入语句相应的数据库表的名称
	 * @return 返回一个包括SQL语句、SQL语句參数值及參数值类型的Map对象
	 */
	public static Map<String, Object> generateInsertExceptNull(Object obj, String tableName) {
		StringBuffer columnStrBuf = new StringBuffer(); // 记录数据表的字段名称
		StringBuffer paramStrBuf = new StringBuffer(); // 记录SQL语句相应插入的占位符
		List<Object> paramValues = new ArrayList<Object>(); // 记录对象參数值
		List<Integer> paramsType = new ArrayList<Integer>(); // 记录參数值类型
		// 查询待插入对象的属性值不为空的属性名称
		List<Object> fieldList = ReflectionUtil.getNotNullField(obj);
		try {
			for (int i = 0; i < fieldList.size(); i  ) {
				Field field = (Field) fieldList.get(i);
				field.setAccessible(true);
				// 记录对象属性名称
				columnStrBuf.append(field.getName());
				if (i != fieldList.size() - 1) {
					columnStrBuf.append(",");
				}
				
				// 记录插入SQL语句的參数占位符
				if("class java.util.Date".equals(field.getType().toString())
						&& field.get(obj) != null){
					String timeStr = DateUtil.formatDate((Date)field.get(obj), "yyyy-MM-dd HH:mm:ss");
					paramStrBuf.append("to_date(?, 'yyyy-MM-dd HH24:mi:ss')");
					paramValues.add(timeStr);
					// 记录对象属性的数据类型
					paramsType.add(getOrclDataType(field.getType().toString()));
				}else{
					paramStrBuf.append("?");
					paramValues.add(field.get(obj));
					// 记录对象属性的数据类型
					paramsType.add(getOrclDataType(field.getType().toString()));
				}
				
				if (i != fieldList.size() - 1) {
					paramStrBuf.append(",");
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		// 生成插入操作的SQL语句
		StringBuffer sb = new StringBuffer();
		sb.append("insert into ");
		sb.append(tableName);
		sb.append(" (");
		sb.append(columnStrBuf);
		sb.append(") ");
		sb.append("values");
		sb.append(" (");
		sb.append(paramStrBuf);
		sb.append(")");
		// 将生成的SQL语句、SQL语句參数值及各參数值的数据类型用map保存并返回
		Map<String, Object> sqlMap = new HashMap<String, Object>();
		sqlMap.put("sql", sb.toString());
		sqlMap.put("paramsValues", paramValues.toArray());
		sqlMap.put("paramsTypes", paramsType.toArray());
		return sqlMap;
	}

	/**
	 * 自己主动生成插入指定对象的SQL语句,包括对象属性的值为空的字段,不包括自增长主键,若不存在,调用时直接置为null.
	 * @param obj 待生成插入SQL语句的对象
	 * @param tableName 待插入语句相应的数据库表的名称
	 * @param keyColumn 数据表主键名称
	 * @return 返回一个包括SQL语句、SQL语句參数值及參数值类型的Map对象
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	public static Map<String, Object> generateInsertWithNull(Object obj, 
			String tableName, String keyColumn) throws IllegalArgumentException, IllegalAccessException {
		StringBuffer columnStrBuf = new StringBuffer(); 
		StringBuffer paramStrBuf = new StringBuffer(); // 记录SQL语句相应插入的占位符
		List<Object> columnNameList = new ArrayList<Object>(); // 记录数据表的字段名称
		List<Object> paramValues = new ArrayList<Object>(); // 记录对象參数值
		List<Integer> paramsType = new ArrayList<Integer>(); // 记录參数值类型
		Field[] fields = obj.getClass().getDeclaredFields();
		for(int i = 0; i < fields.length; i  ){
			fields[i].setAccessible(true);
			// 记录对象属性名称
			if(!fields[i].getName().equalsIgnoreCase(keyColumn)){ // 非主键列记录插入SQL语句的參数占位符
				columnStrBuf.append(fields[i].getName());
				columnNameList.add(fields[i].getName());
				if (i != fields.length - 1) {
					columnStrBuf.append(",");
				}
				if("class java.util.Date".equals(fields[i].getType().toString())
						&& fields[i].get(obj) != null){
					String timeStr = DateUtil.formatDate((Date)fields[i].get(obj), "yyyy-MM-dd HH:mm:ss");
					paramStrBuf.append("to_date(?, 'yyyy-MM-dd HH24:mi:ss')");					paramValues.add(timeStr);					// 记录对象属性的数据类型					paramsType.add(getOrclDataType(fields[i].getType().toString()));				}else{					paramStrBuf.append("?");					paramValues.add(fields[i].get(obj));					// 记录对象属性的数据类型					paramsType.add(getOrclDataType(fields[i].getType().toString()));				}				if (i != fields.length - 1) {					paramStrBuf.append(",");				}			}		}		// 生成插入操作的SQL语句		StringBuffer sb = new StringBuffer();		sb.append("insert into ");		sb.append(tableName);		sb.append(" (");		sb.append(columnStrBuf);		sb.append(") ");		sb.append("values");		sb.append(" (");		sb.append(paramStrBuf);		sb.append(")");		// 将生成的SQL语句、SQL语句的列名称用map保存并返回		Map<String, Object> sqlMap = new HashMap<String, Object>();			/*				System.out.println(sb.toString());		System.out.println(columnNameList.toString());		System.out.println(paramValues.toString());		System.out.println(paramsType.toString());	*/				sqlMap.put("sql", sb.toString());		sqlMap.put("columnNameList", columnNameList.toArray());		sqlMap.put("paramsValues", paramValues.toArray());		sqlMap.put("paramsTypes", paramsType.toArray());		return sqlMap;	}			/**	 * 自己主动生成更新指定对象的SQL语句	 * @param obj 待生成更新SQL语句的对象	 * @param tableName 待更新语句相应的数据库表的名称	 * @param keyColumn 待更新记录的限定字段	 * @return 返回一个包括SQL语句及參数值的数组	 */	public static Object[] generateUpdate(Object obj, String tableName, String keyColumn) {		StringBuffer columnSB = new StringBuffer();		List<Object> params = new ArrayList<Object>();		Object keyValue = null;		// 获取属性值不为空的数据表字段名称		List<Object> fieldList = ReflectionUtil.getNotNullField(obj);		try {			for (int i = 0; i < fieldList.size(); i  ) {				Field field = (Field) fieldList.get(i);				field.setAccessible(true);				if (field.getName().equalsIgnoreCase(keyColumn)) {					keyValue = field.get(obj);				} else {					columnSB.append(field.getName());						if("class java.util.Date".equals(field.getType().toString())							&& field.get(obj) != null){						String timeStr = DateUtil.formatDate((Date)field.get(obj), "yyyy-MM-dd HH:mm:ss");						columnSB.append("=to_date(?, 'yyyy-MM-dd HH24:mi:ss')");						params.add(timeStr);					}else{						columnSB.append("=?");						params.add(field.get(obj));					}					if (i != fieldList.size() - 1) {						columnSB.append(",");					}				}			}		} catch (Exception e) {			throw new RuntimeException(e);		}		if (keyValue == null) {			throw new IllegalArgumentException("数据表 ["   tableName  "] 中的字段'" keyColumn "'的值不能为空.");		}else{			params.add(keyValue);		}		StringBuffer sb = new StringBuffer();		sb.append("update ");		sb.append(tableName);		sb.append(" set ");		if(columnSB.length() >= 0){			sb.append(columnSB);		}else{			sb.append(keyColumn);			sb.append("=? ");			params.add(keyValue);		}				sb.append(" where ");		sb.append(keyColumn);		sb.append("=? ");		return new Object[] { sb.toString(), params.toArray() };	}		/**	 * 返回java数据类型相应的Oracle数据库的数据类型值	 * @param javaType java数据类型	 * @return 返回Oracle数据表的字段数据类型	 */	public static int getOrclDataType(String javaType){		if("class java.lang.String".equals(javaType)){			return java.sql.Types.VARCHAR;		}else if("class java.lang.Integer".equals(javaType) || "int".equals(javaType)){			return java.sql.Types.INTEGER;		}else if("class java.lang.Double".equals(javaType) || "double".equals(javaType)){			return java.sql.Types.DOUBLE;		}else if("class java.lang.Float".equals(javaType) || "float".equals(javaType)){			return java.sql.Types.FLOAT;		}else if("char".equals(javaType)){			return java.sql.Types.CHAR;		}else if("class java.lang.Long".equals(javaType) || "long".equals(javaType)){			return java.sql.Types.NUMERIC;		}else if("class java.util.Date".equals(javaType)){			return java.sql.Types.DATE;		}else{			return java.sql.Types.VARCHAR;		}	}	/**	 * 生成SQL语句中的where子句及where子句中參数值	 * @param obj where条件子句的对象	 * @return 返回条件不为空的where子句	 * @throws Exception 	 * @throws  	 */	public static Map<String, Object> generateWhereStr(Object obj) throws  Exception{		StringBuffer whereStrBuf = new StringBuffer(); // where子句		List<Object> whereParamValues = new ArrayList<Object>(); // where子句中的參数值		whereStrBuf.append("  where 1 = 1 ");		if(obj != null){			Field[] fields = obj.getClass().getDeclaredFields();			for(int i = 0; i < fields.length; i  ){				fields[i].setAccessible(true);				Object columnName = fields[i].get(obj);				if(columnName != null && !"".equals(columnName)){					whereStrBuf.append(" and ");					whereStrBuf.append(fields[i].getName());					whereStrBuf.append("=?");					whereParamValues.add(columnName);				}			}					}		Map<String, Object> whereMap = new HashMap<String, Object>();		/*		System.out.println(whereStrBuf.toString());		System.out.println(whereParamValues);		*/		whereMap.put("whereStr", whereStrBuf.toString());		whereMap.put("whereParamValues", whereParamValues.toArray());		return whereMap;	}}

(6)扩展JAVA对象的反射工具类

代码语言:javascript复制
package com.jkitn.jkits.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 说明:扩展JAVA对象的反射机制
 * @author xdweleven
 * @version 1.0 
 */
public class ReflectionUtil {

	/**
	 * 设置对象的指定属性名称的属性值
	 * @param obj 待设置的对象
	 * @param fieldName 对象属性名称
	 * @param value 属性值
	 */
	public static void setFieldValue(Object obj, String fieldName, Object value) {
		Class<? extends Object> c = obj.getClass();
		try {
			Field field = null;
			Field[] fields = c.getDeclaredFields();
			for(int i = 0; i < fields.length; i  ){
				String fieldNameTemp = fields[i].getName();
				if(fieldNameTemp.equalsIgnoreCase(fieldName)){
					field = c.getDeclaredField(fieldNameTemp);
					field.setAccessible(true);
					field.set(obj, value);
					return;
				}
			}	
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 获取对象的指定属性名称的属性值
	 * @param obj 待设置的对象
	 * @param fieldName 对象属性名称
	 */
	public static Object getFieldValue(Object obj, String fieldName) {
		Class<? extends Object> c = obj.getClass();
		Field[] fields = c.getDeclaredFields();
		try {
			for(int i = 0; i < fields.length; i  ){
				if(fields[i].getName().equalsIgnoreCase(fieldName)){
					fields[i].setAccessible(true);
					return fields[i].get(obj);
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return null;
	}

	/**
	 * 获取对象的属性值不为空的属性名称
	 * @param obj 待获取的对象
	 * @return 返回属性值不为空的对象的属性名称列表
	 */
	public static List<Object> getNotNullField(Object obj) {
		Class<? extends Object> c = obj.getClass();
		List<Object> list = new ArrayList<Object>();
		try {
			Field[] fields = c.getDeclaredFields();
			for(int i = 0; i < fields.length; i  ){
				fields[i].setAccessible(true);
				if(fields[i].get(obj) != null){
					list.add(fields[i]);
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return list;
	}	 
}

(7)定义实现数据库的CRUD基本操作BaseDao

代码语言:javascript复制
package com.jkitn.jkits.dao.common;

import java.io.Serializable;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;

import com.jkitn.jkits.common.DBConn;
import com.jkitn.jkits.common.PageBean;
import com.jkitn.jkits.util.ReflectionUtil;
import com.jkitn.jkits.util.SQLUtil;

/**
 * 说明:封装实现数据库的CRUD相关的底层操作。
 * @author xdweleven
 * @version 1.0 
 */
public class BaseDao{
	// 获取数据库链接实例
    private DBConn dbconn = new DBConn();
	/** 数据库表的前缀  */
	public static final String TB_PREFIX = "tb_jkit_";
	/** 数据库表的查询前缀  */
	public static final String SELECT_TB_PREFIX = "select * from tb_jkit_";
	/** 升序排列  */
	public static final String ASC = "asc";
	/** 降序排列 */
	public static final String DESC = "desc";

	/**
	 * 依据ID查找对象 
	 * @param classType 对象类型
	 * @param columnName 编号字段名称
	 * @param id 对象编号
	 * @return 返回实体对象
	 */
	public <T> T queryById(Class<T> classType, String columnName, Serializable id) 
			throws Exception{
		StringBuffer sqlBuffer = new StringBuffer();
		sqlBuffer.append(SELECT_TB_PREFIX);
		sqlBuffer.append(this.toLowerCaseFirstOne(classType.getSimpleName()));
		sqlBuffer.append(" where ");
		sqlBuffer.append(columnName);
		sqlBuffer.append(" = ? ");
		this.showSQL(sqlBuffer.toString());
		return dbconn.execQuery(sqlBuffer.toString(), new RowMapper<T>(classType),
					new Object[]{id}).get(0);
	}
	
	/**
	 * 查询全部指定class类型的对象信息
	 * @param classType 对象类型
	 * @return 返回实体对象列表
	 */
	public <T> List<T> queryAll(Class<T> classType) throws Exception{
		String sql = SELECT_TB_PREFIX   this.toLowerCaseFirstOne(classType.getSimpleName());
		this.showSQL(sql);
		return dbconn.execQuery(sql, new RowMapper<T>(classType));
	}
	
	 /**
     * 查询指定对象类型的对象信息,并依照指定的排序字段进行升序或降序排序
     * @param classType 对象类型
     * @param orderColumn 排序字段
     * @param ascOrDesc 降序或升序:asc表示升序。desc表示降序
     * @return 返回实体对象列表
     */
	public <T> List<T> queryAllWithOrder(Class<T> classType, String orderColumn, 
			String ascOrDesc) throws Exception{
		StringBuffer sqlBuffer = new StringBuffer();
		sqlBuffer.append(SELECT_TB_PREFIX);
		sqlBuffer.append(this.toLowerCaseFirstOne(classType.getSimpleName()));
		sqlBuffer.append(" order by ");
		sqlBuffer.append(orderColumn);
		sqlBuffer.append(" ");
		sqlBuffer.append(ascOrDesc);
		this.showSQL(sqlBuffer.toString());
		return dbconn.execQuery(sqlBuffer.toString(), new RowMapper<T>(classType));
	}
	
	/**
     * 查询指定SQL语句的对象信息列表
     * @param sql 查询语句
     * @param classType 对象类型
     * @param params SQL语句參数
     * @return 返回实体对象列表
     */
	public <T> List<T> query(String sql, Class<T> classType, Object... params) 
			  throws Exception{
		this.showSQL(sql);
		return dbconn.execQuery(sql, new RowMapper<T>(classType), params);
	}
	
	/**
     * 查询指定SQL语句的对象信息列表
     * @param sql 查询语句
     * @param classType 对象类型
     * @param params SQL语句參数
     * @return 返回实体对象列表
     */
	public <T> T queryForObj(String sql, Class<T> classType, Object... params) 
			throws Exception{
		this.showSQL(sql);
		return dbconn.execQuery(sql, new RowMapper<T>(classType), params).get(0);
	}
	
    /**
     * 分页查询实体对象列表信息
     * @param sql 原始的SQL语句
     * @param classType 对象类型
     * @param curPage 当前页码
     * @param rowsPerPage 每页显示的记录数
     * @param params SQL语句參数
     * @return 返回当前页码的分页对象
     */
	public <T> PageBean<T> queryByPage(String sql, Class<T> classType, int curPage, 
			int rowsPerPage, Object... params) throws Exception{
		 // 获取记录总数
		 int totalRows = this.getTotalRows(sql, params);
		 PageBean<T> pageBean = new PageBean<T>();
		 pageBean.setCurPage(curPage); // 设置当前页码
		 pageBean.initPageBean(totalRows, rowsPerPage); // 初始化分页对象的相关属性
		 // 生成当前分页查询语句(MySql)
		 String pageSql = pageBean.getPageMySQL(sql, curPage, rowsPerPage);
		 this.showSQL(pageSql);
		 // 运行查询操作
		 pageBean.setPageList(dbconn.execQuery(sql, new RowMapper<T>(classType), params));
		 return pageBean;
	}
	
	 /**
     * 保存对象到数据库中,若数据库中的用户表有自增序列,则须要指出表中自增列的字段名称,另外,
	 * 数据库中相应的自增序列的名称需按例如以下格式取名:class名称_自增列字段名称_SEQ,
	 * 比如用户的class为Users,自增序列字段名称为id,则数据库中的自增序列的名称取名为USERS_ID_SEQ.
     * @param obj 实体对象
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* * @param sequenceKeyColumn 数据表自增序列的字段名称,若不存在。则置为null。     * @return 返回被更新的记录数	 * @throws IllegalAccessException 	 * @throws IllegalArgumentException      */	public <T> int insert(T obj, String sequenceKeyColumn) throws Exception{		String tableName = TB_PREFIX   this.toLowerCaseFirstOne(obj.getClass().getSimpleName());		// 自己主动生成对象的无自增序列插入SQL语句及其相关插入的參数值和类型		Map<String, Object> sqlMap = SQLUtil.generateInsertWithNull(obj, tableName, sequenceKeyColumn);		String sql = sqlMap.get("sql").toString(); // SQL语句		Object[] paramsValues = (Object[])sqlMap.get("paramsValues"); // SQL语句的參数值		// int[] paramsTypes = this.parseArrayToInt((Object[])sqlMap.get("paramsTypes")); // 參数值类型		this.showSQL(sql);		return dbconn.execUpdate(sql, paramsValues);	}	    /**     * 更新对象     * @param obj 待更新的实体对象     * @param keyColumn 更新对象的限定条件字段名称     * @return 返回被更新的记录数     */	public <T> int update(T obj, String keyColumn) throws Exception{		String tableName = TB_PREFIX   this.toLowerCaseFirstOne(obj.getClass().getSimpleName());		// 自己主动生成对象的更新操作的SQL语句及其參数值		Object[] updateSql = SQLUtil.generateUpdate(obj, tableName, keyColumn);		this.showSQL(updateSql[0].toString());		return dbconn.execUpdate(updateSql[0].toString(), (Object[])updateSql[1]);	}		/**     * 删除对象     * @param obj 待更新的实体对象     * @param keyColumn 删除的限定条件字段     * @return 返回被删除的记录数     */	public <T> int delete(T obj, String keyColumn) throws Exception{		// 获取限定条件的值		Object keyValue = ReflectionUtil.getFieldValue(obj, keyColumn);		if(keyValue == null){			throw new RuntimeException("[" obj.getClass() "]中不存在属性'" keyColumn "'或属性值为空.");		}		StringBuffer sqlBuffer = new StringBuffer();		sqlBuffer.append("delete from ");		sqlBuffer.append(TB_PREFIX);		sqlBuffer.append(this.toLowerCaseFirstOne(obj.getClass().getSimpleName()));		sqlBuffer.append(" where ");		sqlBuffer.append(keyColumn);		sqlBuffer.append(" = ? ");		this.showSQL(sqlBuffer.toString());		return dbconn.execUpdate(sqlBuffer.toString(), keyValue.toString());	}		/**     * 删除指定编号的实体对象     * @param classType 对象类型     * @param keyColumn ID相应的数据表列名称     * @param id 实体对象编号     * @return 返回删除的记录数     */	public <T> int deleteById(Class<T> classType, String keyColumn, Serializable id) 			throws Exception{		StringBuffer sqlBuffer = new StringBuffer();		sqlBuffer.append("delete from ");		sqlBuffer.append(TB_PREFIX);		sqlBuffer.append(this.toLowerCaseFirstOne(classType.getSimpleName()));		sqlBuffer.append(" where ");		sqlBuffer.append(keyColumn);		sqlBuffer.append(" = ? ");		this.showSQL(sqlBuffer.toString());		return dbconn.execUpdate(sqlBuffer.toString(), id);	}		 /**     * 批量删除指定编号的实体对象     * @param classType 对象类型     * @param idColumnName 编号字段名称      * @param ids 待删除对象的编号数组     */	public <T> int deleteByIds(Class<T> classType, String idColumnName,			Serializable[] ids) throws Exception{		StringBuffer sqlBuffer = new StringBuffer();		sqlBuffer.append("delete from ");		sqlBuffer.append(TB_PREFIX);		sqlBuffer.append(this.toLowerCaseFirstOne(classType.getSimpleName()));		sqlBuffer.append(" where ");		sqlBuffer.append(idColumnName);		sqlBuffer.append(" = ? ");		this.showSQL(sqlBuffer.toString());		int rowNums = 0; // 删除的记录数		for(int i = 0; i < ids.length; i  ){			rowNums  = this.deleteById(classType, idColumnName, ids[i]);		}		return rowNums;	}	    /**     * 更新操作     * @param sql 删除操作的SQL语句     * @param params SQL语句中的參数值     * @return 返回删除的记录数     */	public int update(String sql, Object... params) throws Exception{		this.showSQL(sql);		return dbconn.execUpdate(sql, params);	}		/**     * 批量更新对象     * @param objs 待更新的实体对象列表     * @param keyColumn 主键字段名称     */	public <T> int batchUpdate(List<T> objs, String keyColumn) throws Exception{		if(objs == null || objs.isEmpty()){			return 0;		}		int updateNum = 0;		// 自己主动生成对象的更新操作的SQL语句及其參数值		for(int i = 0; i < objs.size(); i  ){			T obj = objs.get(i);			updateNum  = this.update(obj, keyColumn);		}		return updateNum;	}		 /**     * 批量插入对象     * @param objs 待新增的实体对象列表     * @param keyColumn 数据表主键列名称	 * @throws IllegalAccessException 	 * @throws IllegalArgumentException      */	public <T> int batchInsert(List<T> objs, String keyColumn) throws Exception {		if(objs == null || objs.isEmpty()){			return 0;		}		int updateNum = 0;		// 自己主动生成对象的更新操作的SQL语句及其參数值		for(int i = 0; i < objs.size(); i  ){			T obj = objs.get(i);			updateNum  = this.insert(obj, keyColumn);		}		return updateNum;	}		/**	 * 统计指定统计数量的SQL语句	 * @param sql 待运行的SQL语句	 * @param params SQL语句參数值	 * @return 返回记录总数	 * @throws Exception	 */	public int getTotalRows(String sql, Object... params) throws Exception{		String totalRowsSql = "select count(*) totalRows from ( " sql " )";		this.showSQL(totalRowsSql);		ResultSet rs = dbconn.queryForResultSet(totalRowsSql, params);		while(rs.next()){			return rs.getInt("totalRows");		}		return 0;	}	    /**     * 删除操作     * @param sql 删除操作的SQL语句     * @param params SQL语句中的參数值     * @return 返回删除的记录数     */	public int delete(String sql, Object... params) throws Exception{		this.showSQL(sql);		return dbconn.execUpdate(sql, params);	}	    /**     * 获取下一个指定自增序列的值(MySql)     * @param classType 对象类型     * @param seqColName 自增字段名称     * @return 返回指定表的主键自增序列的最新值     */	public <T> int getNextAutoIncrementVal(Class<T> classType, String seqColName) throws Exception{		StringBuffer sqlBuf = new StringBuffer();		sqlBuf.append("select max(");		sqlBuf.append(seqColName);		sqlBuf.append(") 1 nextId from ");		sqlBuf.append(TB_PREFIX);		sqlBuf.append(this.toLowerCaseFirstOne(classType.getSimpleName()));		this.showSQL(sqlBuf.toString());	    ResultSet rs = dbconn.queryForResultSet(sqlBuf.toString());	    if(rs.next()){	    	return rs.getInt("nextId");	    }else{	    	return 0;	    }	}		/**	 * 首字母转小写	 * @param str 待转换的字符创	 * @return 返回首字母小写后的字符串	 */	public String toLowerCaseFirstOne(String str){	     if(Character.isLowerCase(str.charAt(0))){	          return str;	     }else{	         return (new StringBuilder()).append(Character.toLowerCase(str.charAt(0))).	        		 append(str.substring(1)).toString();	     }	}		/**	 * 首字母转大写	 * @param str 待转换的字符串	 * @return 返回首字母大写的字符串	 */	public String toUpperCaseFirstOne(String str){	     if(Character.isUpperCase(str.charAt(0))){	         return str;	     }else{	         return (new StringBuilder()).append(Character.toUpperCase(str.charAt(0))).	        		 append(str.substring(1)).toString();	     }	}    /**     * 打印SQL语句     * @param sql     */    public void showSQL(String sql){    	System.out.println(sql);    }    }
*/

以上是依据自己的理解封装的一些经常使用DAO层操作,并已运用到部署上线的两个项目中,眼下尚未报出BUG。

但在效率方面,个人认为还有非常多地方须要优化的地方。比方说批量增删改操作。依据我个人PC机測试的结果,使用JDBC自带的批量操作。要比上述简单循环的操作速度要慢,但我还是认为这部分的效率还有非常大的提升空间,希望能有位IT大卡给我指点一二,不胜感激!

版权声明:本文博客原创文章,博客,未经同意,不得转载。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/117558.html原文链接:https://javaforall.cn

0 人点赞