目录
3.2 TableContext.poClassTableMap
3.3 executDML(sql,new Object[]{id})
前言
今天过了两星期回头看看自己写的代码!!!
各位小伙伴们好,本博主是一位球风飘逸,走位风骚,游戏巨强,热爱代码,身体强壮,热爱生活,即将拥有九块腹肌的未来的一位程序员大牛!
插一句,昨天球馆打球,准备秀一波小腹肌。刚一脱衣服,边上小哥也脱了。然后我和他对比了一下。
我大概长这样他大概是这样
鉴于以上情形,后面谁要喊我喝肥仔快乐水我就和谁急~
好了,牛皮吹到这!
今天,本博主将带领着小伙伴们继续搞搞这个ORM框架,首先我们要明确一个事情,框架其实就是帮我们减少开发量。敲黑板其实框架就是一个工具。越简单越好用功能越强大越好。所以各位刚接触框架的小伙伴们也不要听到框架就吓到了。框架就相当于一台挖掘机。这个挖掘机做好了干活很快。以前是自己人工挖土,现在用挖机挖土。效率直接提高10倍以上。
好了,目前我们进行到了第三部分,前两部分进行数据库的服务,表结构信息读取,并创建了对应的实体类,现在我们需要干的很简单,就是对这些表写一些通用的增删改查的方法!当在项目中进行查询的时候就不用自己手动去写最基本的增删改查的方法,或者可以通过自己创建的方式创建一些通用的查询方法。
一、更新类结构
将同步生成的代码移植到TableContext中去。
/**
* 根据表结构,更新配置的po包下面的java类
* 实现了从表结构转化到类结构
*/
public static void updateJavaPOFile(){
Map<String,TableInfo> map = TableContext.tables;
for(TableInfo t:map.values()){
JAVAFileUtils.createJavaPOFile(t,new MySqlTypeConvertor());
}
}
二、查询的接口定义
package sorm.core;
/**
* @ProjectName: SORM
* @Package: com.sorm.core
* @ClassName: Query
* @Author: HAND_WEILI
* @Description: 负责查询(对外提供服务的核心类)
* @Date: 2020/6/7 17:10
* @Version: 1.0
*/
public interface Query {
/**
* 直接执行一个DML语句
* @param sql sql语句
* @param params 参数
* @return 执行SQL语句后影响记录的行数
*/
public int executDML(String sql,Object[] params);
/**
* 将一个对象存储到数据库中
* @param obj 要存储的对象
*/
public void insert(Object obj);
/**
* 根据对象的类型和ID一起
* @param clazz
* @param id
*/
public void delete(Class clazz,Object id);
/**
* 通过对象直接删除
* @param obj
*/
public void delete(Object obj);
}
三、Delete方法介绍
3.1 Delete:删除方法。
我妈教我挑软柿子捏。写代码也从简单的来。
@Override
public void delete(Class clazz, Object id) {
//思路,删除一条数据就是去表
// t_user,2--》delete from t_user id=2
// 通过 class对象找到表对象 tableinfo
// 反过来找数据库的信息
TableInfo tableInfo= TableContext.poClassTableMap.get(clazz);
// 主键
ColumnInfo columnInfo= tableInfo.getOnlyKey();
// 拼接sql语句
String sql ="delete from " + tableInfo.getTname()+ " where "+columnInfo.getName()+" = ? ";
executDML(sql,new Object[]{id});
}
3.2 TableContext.poClassTableMap
这个里面有一个东西要特别指出:
TableContext.poClassTableMap.get(clazz);
此方法是通过读取数据库信息的时候我们将对创建的类,和表名进行匹配(映射)。
/**
* 将po的class对象和表信息对相关关联起来,便于重用!
*/
public static Map<Class,TableInfo> poClassTableMap = new HashMap<Class,TableInfo>();
/**
* 加载po包下面的类
*/
public static void loadPOTables(){
for(TableInfo tableInfo:tables.values()){
try {
// 加载映射类的map
Class c = Class.forName(DBManager.getConf().getPoPackage()
+"."+ StringUtils.fristChar2UpperCase(tableInfo.getTname()));
poClassTableMap.put(c, tableInfo);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
3.3 executDML(sql,new Object[]{id})
另一个方法:
executDML(sql,new Object[]{id}); 该方法用于执行所有的DML语句,SQL是增删改查的语句,而object是参数列表。
@Override
public int executDML(String sql, Object[] params) {
// 执行dmL
Connection connection = DBManager.getConnection();
int count = 0;
PreparedStatement ps =null;
try {
ps = connection.prepareStatement(sql);
JDBCUtils.handleParams(ps,params);
/* if(params!=null){
for(int i=0;i<params.length;i++){
ps.setObject(i+1,params[i]);
}
}*/
System.out.println("执行语句:=> "+sql);
count = ps.executeUpdate();
System.out.println("执行结果="+count);
} catch (SQLException e) {
e.printStackTrace();
}finally {
// 关闭所有的链接
DBManager.close(ps,connection);
}
return 0;
}
其中我将参数列表放入准备语句的这个操作抽离出来到了JDBCUtils中
3.4 第二个删除方法:
@Override
public void delete(Object obj) {
// 思路,直接调用上面的删除方法。
// 直接传对象
Class c =obj.getClass();
TableInfo tableInfo = TableContext.poClassTableMap.get(c);
// 主键
ColumnInfo onlyPriKey= tableInfo.getOnlyKey();
// 通过反射的机制,调用属性的get方法或set方法。
/* try {
Method method = c.getMethod("get"+ StringUtils.fristChar2UpperCase(onlyPriKey.getName()),null);
Object priKeyValue = method.invoke(obj,null);
// 调上面的方法
delete(c,priKeyValue);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}*/
// 上面可以删除
// 以上方法是通过反射去读取,因此我们可以将反射的方法抽离成一个工具类
Object priKeyValue = ReflectUtils.invokeGet(onlyPriKey.getName(),obj);
delete(c,priKeyValue);
}
3.5 抽离反射get方法
通过反射方法获取对应的值也被我抽离出来了放在反射工具类中,常用方法就抽出来了 。
/**
* @ProjectName: SORM
* @Package: com.sorm.utils
* @ClassName: ReflectUtils
* @Author: HAND_WEILI
* @Description: 操作反射相关的工具类
* @Date: 2020/6/10 12:57
* @Version: 1.0
*/
public class ReflectUtils {
/**
* 用于获取get方法的值
* @param fieldName 字段名
* @param obj 目标对象
* @return
*/
public static Object invokeGet(String fieldName,Object obj){
Method m = null;
Class clazz=obj.getClass();
Object priKeyValue =null;
try {
m = clazz.getMethod("get"+ StringUtils.fristChar2UpperCase(fieldName),null);
priKeyValue = m.invoke(obj,null);
// 我们再次调用上个方法。
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return priKeyValue;
}
}
3.6 测试:
由测试结果可以看出表中的数据已经被删除了,这个像不像我们平时使用MyBatis中调用的delete方法一毛一样。只是我们并不是使用的mapper.xml方式,但是实际效果是一样的。
四、Insert方法介绍
4.1 Insert
由于上面我们已经做好了 各个工具类的准备工作了因此我们这次进行方法编写的时候只要关注怎么拼凑一个插入语句就OK了。
@Override
public void insert(Object obj) {
// obj -》对应的表中 insert inot 表名(), values(?,?);
/** 思路:1、通过 obj对象获取到对应的类对象.(反射)
* 2、通过类对象,使用最开始的TableContext.poClassTableMap.获取到对应的TableInfo信息(集合)
* 3、通过TableInfo获取到表名。
* 4、通过Class对象获取到对应的列名,以及对应的列值。
* 5、通过一个 List<Objcect>将参数列表丢进去。
* 6、通过这些信息拼凑成一个 insert 语句然后执行 executDML方法。
*/
StringBuilder sql=new StringBuilder();
List<Object> paramList = new ArrayList<>();
Class clazz = obj.getClass();
TableInfo tableInfo = TableContext.poClassTableMap.get(clazz);
sql.append("insert into "+tableInfo.getTname()+"(");
Field[] fields = clazz.getDeclaredFields();
for(Field field:fields){
if(ReflectUtils.invokeGet(field.getName(),obj)!=null){
sql.append(field.getName()+",");
paramList.add(ReflectUtils.invokeGet(field.getName(),obj));
}
}
// sql.replace(sql.length()-1,sql.length(),")");
sql.setCharAt(sql.length()-1,')');
sql.append(" values(");
for(int i=0 ; i<paramList.size();i++){
sql.append("?,");
}
sql.setCharAt(sql.length()-1,')');
System.out.println(sql);
executDML(sql.toString(),paramList.toArray());
}
4.2测试
五、Upadte方法介绍
5.1Upadte方法
/**
* 更新对象记录
*
* @param obj
* @param fieldName
* @return
*/
public int update(Object obj, String[] fieldName) {
// obj("user")-->update 表名 set uname =?,pwd=? where id =?
// 思路:都懒得写了,和新增没啥区别,小伙子自己看吧。
Class clazz = obj.getClass();
StringBuilder sql = new StringBuilder();
List<Object> paramList = new ArrayList<>();
TableInfo tableInfo = TableContext.poClassTableMap.get(clazz);
ColumnInfo onlyKey=tableInfo.getOnlyKey();
sql.append(" update "+tableInfo.getTname()+" set ");
for(String str:fieldName){
sql.append(str+"=?,");
paramList.add(ReflectUtils.invokeGet(str,obj));
}
sql.setCharAt(sql.length()-1,' ');
sql.append("where "+onlyKey.getName()+"=?");
paramList.add(ReflectUtils.invokeGet(onlyKey.getName(),obj));
System.out.println(sql);
return executDML(sql.toString(),paramList.toArray());
}
5.2 测试
六:总结
到此,基本上我们这个小框架其实已经做完了。剩下的只有一个查询了,查询相对麻烦一点,多行,多列。单行,单列。联合查询。以及分页。后面不一定再写篇博客了。基本上到这,整个思路都出来了~~~觉得有兴趣的小伙伴可以去我的git上拷一份自己玩一玩。
七:展望
最近我在公司的产品工作,作为一个想成为大牛的程序员。我们对自己的代码,产品,业务都要有深刻的了解。我希望作为一个程序员一定要记住一句话技术都是为了业务进行服务的,不要脱离业务。很久不写JAVA代码,熟练程度降低了很多,但是我们记住一句话都一样,程序都一样。
这是工作上的,接下来是个人学习上的。没办法上了程序员这条贼船~就要不停的学习,毕竟5年换一批技术栈。但是,我们要深刻的认识到不管怎么换,核心,算法,数据结构,计算机原理,这些东西是不会跑的,该学的还是要认真的去学。说回自己,目前,我觉得我自己的技术深度,技术的宽度都是不够的~和大牛们有很大的区别。我个人觉得我应该先拓展自己的技术宽度。就JAVA企业开发的这一套,需要自己去搭建。就相当于自己是一个小项目的负责人。从系统构建,数据库设计,表结构设计,整个技术栈的挑选都需要自己去思考。是否符合相对应的业务场景。因此,后面我应该会基于SPRING BOOT,SPRING CLOUD开发一个微服务的小系统,用于掌握,服务器(Linux),redis,集群等等这些东西的使用。因此后面有兴趣的小伙伴们可以跟着我一起玩一玩。技术吗,就是用来玩的。然后更远的念想就是做一个自己的公众微信号~!
这个微服的项目大概是一个票务网站到时候写博客的时候细说。
然后今天的代码地址是
git 克隆地址:https://github.com/WeiLi14/SORM.git
我是帅哥威,一个即将拥有九块腹肌的立志成为一名全栈工程师的匠人!写文章,超辛苦的~小伙伴们不给我点点赞?
上一篇地址:orm框架实现-----01(数据库链接)