需要实现的功能:根据实体类自动生成Sql语句与参数。
基本思路是:在实体类上标识注解,使用反射读取注解然后拼接Sql语句。
哦了,开始研究代码~
有请主人公注解:
两个注解,分别标识类与属性
然后上解析类:
根据对象获得Sql语句与参数。,解析方法太多了~咱们主要讲一下修改吧,它最全面了
第一部分
第二部分
第三部分
修改方法 大概就这样,我下面会粘贴一些代码 ,
然后是自动装载结果方法
然后补充一个通用方法,修改方法里用的过
这样返回的Map中就有两个参数 一个是sql语句另一个是参数数组,然后我们看一下BaseDao的代码:
没啥说的~获得连接与关闭连接
数据修改方法(增删改用):
数据查询通用方法:
注意返回的是ResultSet,交由解析类处理
增删改方法:
只是调用解析类的方法不同而已。
查询一个方法:
查询所有方法:
这就是BaseDao的所有方法了。好了准备测试了。
我们首先建两个表 分别为员工表与部门表吧~
员工表 四个字段 分别是 员工编号(主键,非自增),姓名,年龄,备注
部门表 就一个自增主键 与名称,Sql语句如下
然后创建对应的实体类,并标识注解。
这里我故意没有使表名与属性与数据库同名,推荐还是使用相同的名称
实体类OK,我们来测试类,先插入一条员工信息与部门信息
一个无比简单的测试类
然后看执行结果
打印出了语句 ,空格太大是我拼接的不好 哭~
看数据库
成功加入了,
测试修改
代码(偷偷的加上了部门的主键):
运行结果:
数据库:
修改成功!
删除就只删掉一个部门好了:
三连图:
结果
数据库
删除也成功了,最后测试下查询方法,我们根据员工编号进行查询一个员工,
三连图:代码-数据库-执行结果
数据库
运行结果:
成功!
最后一个查询全部 我先去插一些无用的数据先~
三连图:
哈哈成功了~。
这个注解与反射结合的小例子就到这了~,代码待优化,有很多可以在封装,也没有验证。优化就交给你练习时啦 哈哈。
最后补上解析类代码(极度需要优化)
package com.jack.util;
import java.sql.ResultSet;
import java.util.List;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.jack.annotation.DataBaseColumn;
import com.jack.annotation.DataBaseTable;
public class AnalysisUtil {
/**
* 解析方法(保存)
*
* @return 数据库需要信息
*/
public Map<String, Object> analysisSave(Object obj)throws Exception {
StringBuilder sql = new StringBuilder("insert into ");
List<Object> params = new ArrayList<Object>();
Class<?> cls = obj.getClass(); // 获得类信息
// 获得类注解信息
DataBaseTable tbAnnotation = cls.getAnnotation(DataBaseTable.class);
//如果
if (null != tbAnnotation) {
String tableName = tbAnnotation.tableName();
sql.append(tableName + "(");
Field[] declaredFields = cls.getDeclaredFields();
for (Field field : declaredFields) {
DataBaseColumn clAnnotation = field.getAnnotation(DataBaseColumn.class);
if (null != clAnnotation) {
String columnName = clAnnotation.columnName();
boolean identity = clAnnotation.isIdentity();
if(identity){
continue;
}else{
sql.append(columnName+",");
}
}
}
String substring = sql.substring(0, sql.length()-1);
sql.delete( 0, sql.length() );
sql.append(substring+") ");
sql.append(" values(");
for (Field field : declaredFields) {
DataBaseColumn clAnnotation = field.getAnnotation(DataBaseColumn.class);
if (null != clAnnotation) {
boolean identity = clAnnotation.isIdentity();
if(identity){
continue;
}else{
sql.append("?,");
Object fieldValue = getFieldValue(field, obj);
params.add(fieldValue);
}
}
}
String strSql = sql.substring(0, sql.length()-1);
sql.delete( 0, sql.length() );
sql.append(strSql+")");
}
Map<String, Object> map =new HashMap<String, Object>();
map.put("sql", sql.toString());
map.put("params", params);
return map;
}
/**
* 解析方法(修改)
* @param obj
* @return
* @throws Exception
*/
public Map<String, Object> analysisEdit(Object obj)throws Exception {
List<Object> params = new ArrayList<Object>();
Class<?> cls = obj.getClass(); // 获得类信息
//拼接语句
StringBuilder sql = new StringBuilder("update ");
// 获得类注解信息
DataBaseTable tbAnnotation = cls.getAnnotation(DataBaseTable.class);
//如果有注解,即是数据库表
if (null != tbAnnotation) {
//获得表名称
String tableName = tbAnnotation.tableName();
sql.append(tableName + " set ");
//获得所有属性
Field[] declaredFields = cls.getDeclaredFields();
//记录一下主键的名称与值
String primaryName = null;
Object primaryValue = null;
//循环遍历属性
for (Field field : declaredFields) {
//获得属性注解
DataBaseColumn clAnnotation = field.getAnnotation(DataBaseColumn.class);
//如果注解不为空,则表示标识为数据库列了
if (null != clAnnotation) {
//获得三个属性,列名,是否是主键,是否自增是
String columnName = clAnnotation.columnName();
boolean primaryKey = clAnnotation.isPrimaryKey();
boolean identity = clAnnotation.isIdentity();
//如果是主键列,则不进行修改,记录名称与值
if(primaryKey){
primaryName =columnName;
primaryValue = getFieldValue(field, obj);
continue;
}else if(identity){ //自增列同样不修改
continue;
}else{
//拼接信息
sql.append(columnName+"=?,");
//调用一个获得值的方法
Object fieldValue = getFieldValue(field, obj);
params.add(fieldValue);
}
}
}
//最后出了循环拼接主键信息 ,如果没主键 就会执行无效,但是不会报错
String substring = sql.substring(0, sql.length()-1);
sql.delete( 0, sql.length() );
sql.append(substring);
sql.append(" where "+primaryName+" = ?");
params.add(primaryValue);
}
//放入Map中
Map<String, Object> map =new HashMap<String, Object>();
map.put("sql", sql.toString());
map.put("params", params);
return map;
}
/**
* 解析方法(删除)
* @param obj
* @return
* @throws Exception
*/
public Map<String, Object> analysisDelete(Object obj)throws Exception{
StringBuilder sql = new StringBuilder("delete from ");
List<Object> params = new ArrayList<Object>();
Class<?> cls = obj.getClass(); // 获得类信息
// 获得类注解信息
DataBaseTable tbAnnotation = cls.getAnnotation(DataBaseTable.class);
if (null != tbAnnotation) {
String tableName = tbAnnotation.tableName();
sql.append(tableName);
Field[] declaredFields = cls.getDeclaredFields();
for (Field field : declaredFields) {
DataBaseColumn clAnnotation = field.getAnnotation(DataBaseColumn.class);
if (null != clAnnotation) {
String columnName = clAnnotation.columnName();
boolean primaryKey = clAnnotation.isPrimaryKey();
if(primaryKey){
sql.append(" where "+columnName+" = ?");
Object fieldValue = getFieldValue(field, obj);
params.add(fieldValue);
}
}
}
}
Map<String, Object> map =new HashMap<String, Object>();
map.put("sql", sql.toString());
map.put("params", params);
return map;
}
/**
* 解析方法(根据编号获得一个)
* @param obj
* @return
* @throws Exception
*/
public Map<String, Object> analysisFindById(Object obj)throws Exception{
StringBuilder sql = new StringBuilder("select * from ");
List<Object> params = new ArrayList<Object>();
Class<?> cls = obj.getClass(); // 获得类信息
// 获得类注解信息
DataBaseTable tbAnnotation = cls.getAnnotation(DataBaseTable.class);
if (null != tbAnnotation) {
String tableName = tbAnnotation.tableName();
sql.append(tableName);
Field[] declaredFields = cls.getDeclaredFields();
for (Field field : declaredFields) {
DataBaseColumn clAnnotation = field.getAnnotation(DataBaseColumn.class);
if (null != clAnnotation) {
String columnName = clAnnotation.columnName();
boolean primaryKey = clAnnotation.isPrimaryKey();
if(primaryKey){
sql.append(" where "+columnName+" = ?");
Object fieldValue = getFieldValue(field, obj);
params.add(fieldValue);
}
}
}
}
Map<String, Object> map =new HashMap<String, Object>();
map.put("sql", sql.toString());
map.put("params", params);
return map;
}
/**
* 解析方法,查询全部
* @param obj
* @return
* @throws Exception
*/
public Map<String, Object> analysisFindAll(Class<?> cls)throws Exception{
StringBuilder sql = new StringBuilder("select * from ");
List<Object> params = new ArrayList<Object>();
// 获得类注解信息
DataBaseTable tbAnnotation = cls.getAnnotation(DataBaseTable.class);
if (null != tbAnnotation) {
sql.append(tbAnnotation.tableName());
}
Map<String, Object> map =new HashMap<String, Object>();
map.put("sql", sql.toString());
map.put("params", params);
return map;
}
/**
* 解析装载结果方法
* @param cls 结果类
* @param rs 结果集ResultSet
* @return
* @throws Exception
*/
public List<Object> analysisResult(Class<?> cls,ResultSet rs)throws Exception{
List<Object> list =new ArrayList<Object>();
while(rs.next()){
Object obj = cls.newInstance(); //创建一个对象
Field[] fields = cls.getDeclaredFields(); //获得所有属性信息
for (Field field : fields) { //循环所有属性
DataBaseColumn annotation = field.getAnnotation(DataBaseColumn.class);
if(null!=annotation){
//获得方法名称,首字母转大写+set
String name = "set"+this.firstToUpperCase(field.getName());
//获得方法 第二个参数为属性类型一定等于set方法的参数类型
Method method = cls.getMethod(name, field.getType());
//执行方法
method.invoke(obj, rs.getObject(annotation.columnName()));
}
}
list.add(obj);
}
return list;
}
/**
* 获得属性值方法
* @param field
* @param obj
* @return
* @throws Exception
*/
@SuppressWarnings("unused")
private Object getFieldValue(Field field,Object obj) throws Exception{
//获得Get方法名称
String fieldName = field.getName();
String methodName = "get"+this.firstToUpperCase(fieldName);
//获得方法
Method declaredMethod = obj.getClass().getDeclaredMethod(methodName, null);
if(null !=declaredMethod){
return declaredMethod.invoke(obj, null);
}
return null;
}
/**
* 首字母转大写
* @param name 字符串
* @return 转大写的字符串
*/
public String firstToUpperCase(String name){
return name.substring(0,1).toUpperCase()+name.substring(1);
}
}