利用实体bean对象批量数据传输处理

需求

现在有两方数据库表结构相同,一方A、另一个方B,现想从A处查询出多个表的数据,传输到B地保存起来。

解决方案1

最简单粗暴的方法就是,查询出A处相关表的数据封装到实体对象中,之后放到List集合中,再传递给B处,B处再遍历集合,将数据保存到B处。但是此处的问题是想要再添加一个表的数据时,需要改查询的代码还需要改保存的代码,非常麻烦,所以不建议使用。

方案2

  1. 新建一个需要准备哪些数据的实体类对象
  • 待查询的猫
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Cat { private String id; private String food; private String weight; private String height; }
  • 待查询的狗
@Data
@AllArgsConstructor
public class Dog { private String id; private String food; private String weight; private String height;
}
  • 待查询的猪
@Data
@AllArgsConstructor
public class Pig { private String id; private String food; private String weight; private String height; private String pid;
}
  • 自定义传输实体对象,这里定义了需要查询那些集合对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CustomDataTransferDTO{ /**
* ===============================================================
* 数据查询结果
* ===============================================================
*/
/**
* 待查询的猫信息
*/
private List<Cat> catList; /**
* 待查询的狗信息 通过注解来明确关联关系
*/
@CustomAnnotation.connectTable(tablePath = "com.study.customdatatransfer.Pig")
private List<Dog> dogList; /**
* 待查询的猪信息
*/
@Ignore
private List<Pig> pigList;
  1. 新建参数关系类
  • 公共参数关系类
/**
* 这里为共通参数信息设置
* @author jieya
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonParameterDTO { /**
* ===============================================================
* 这里配置所有集合查询的公共查询条件
* ===============================================================
*/
/**
* 主键信息
*/
public String id; }
  • 自定义查询参数
/**
* 自定义查询条件及关联表信息查询实体对象
* @author Administrator
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TableAndParamsDTO { /**
* 主表名 这里是查询那个实体对象的数据,这里的table值一定要和CustomDataTransferDTO中的List的泛型对上
*/
@CustomAnnotation.Table
private String table;
/**
* ===============================================================
* 自定义参数
* ===============================================================
*/
/**
* 自定义查询参数 search 标记这是一个查询参数
*/
@CustomAnnotation.search
private String food; /**
* connectSearchTerm(term = "id") 这个标记为这是连表查询的副表,主表的id等于副表的pid
*/
@CustomAnnotation.connectSearchTerm(term = "id")
private String pid;
}
  1. 新建自定义处理主方法
/**
* 自定义数据处理主方法
*
* @author Administrator
*/
public class CustomDataMain { private static final List<Cat> catList = new ArrayList<>();
private static final List<Dog> dogList = new ArrayList<>();
private static final List<Pig> pigList = new ArrayList<>();
private static List<TableAndParamsDTO> tableAndParamsList = new ArrayList();
private static CommonParameterDTO commonParameter = new CommonParameterDTO(); static {
catList.add(new Cat("1", "面包1", "10", "12"));
catList.add(new Cat("2", "面包2", "10", "12"));
catList.add(new Cat("3", "面包3", "10", "12"));
catList.add(new Cat("4", "面包4", "10", "12")); dogList.add(new Dog("1", "米饭1", "10", "12"));
dogList.add(new Dog("2", "米饭2", "10", "12"));
dogList.add(new Dog("3", "米饭3", "10", "12"));
dogList.add(new Dog("4", "米饭4", "10", "12")); pigList.add(new Pig("1", "麻辣烫1", "10", "12", "1"));
pigList.add(new Pig("2", "麻辣烫2", "10", "12", "2"));
pigList.add(new Pig("3", "麻辣烫3", "10", "12", "3"));
pigList.add(new Pig("4", "麻辣烫4", "10", "12", "4"));
} public static void main(String[] args) throws Exception {
// 共通参数
commonParameter.setId("1");
//
TableAndParamsDTO tableAndParamsDTO = new TableAndParamsDTO();
tableAndParamsDTO.setTable("Pig");
tableAndParamsDTO.setFood("麻辣烫1");
tableAndParamsDTO.setPid("id");
tableAndParamsList.add(tableAndParamsDTO);
findCustomData(CustomDataTransferDTO.class);
} public static Object findCustomData(Class<?> clazz) throws Exception { // 实例化数据传输类
Object obj = clazz.newInstance(); // 首先得到pojo所定义的字段
Field[] fields = clazz.getDeclaredFields();
for (Field curField : fields) {
// 设置字段可访问(必须,否则报错)
curField.setAccessible(true);
// 如果
if (!curField.isAnnotationPresent(Ignore.class)) {
CustomAnnotation.connectTable annotation = curField.getAnnotation(CustomAnnotation.connectTable.class);
String sideTablePath = null;
if (annotation != null) {
sideTablePath = annotation.tablePath();
} Class<?> curFieldType = curField.getType();
// 集合List元素
if (curFieldType.equals(List.class)) {
// 当前集合的泛型类型
Type genericType = curField.getGenericType();
if (null == genericType) {
continue;
}
if (genericType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genericType;
// 得到泛型里的class类型对象
Class<?> actualTypeArgument = (Class<?>) pt.getActualTypeArguments()[0];
// 获取完整路径信息
String tablePath = actualTypeArgument.getName();
// 获取实体对象名称
String tableName = actualTypeArgument.getSimpleName();
// 获取该实体对象设置的自定义信息
TableAndParamsDTO tableAndParams = tableAndParamsList.stream().filter(o -> o.getTable().equals(tableName)).findAny().orElse(null);
// 拼接hql和执行获取数据
obj = connectSqlAndExexute(obj, clazz, tablePath, tableAndParams, sideTablePath);
}
} else {
System.out.println(curField.getName() + "--暂不支持的类型--" + curFieldType.getSimpleName());
}
} else {
System.out.println("Ignore----");
}
}
return null;
} /**
* 连接sql并获取数据
*
* @param obj
* @param clazz
* @param tablePath
* @param tableAndParams
* @param sideTablePath
* @return
* @throws Exception
*/
private static Object connectSqlAndExexute(Object obj, Class<?> clazz, String tablePath,
TableAndParamsDTO tableAndParams, String sideTablePath) throws Exception {
int lastIndex = tablePath.lastIndexOf(".");
String tableName = tablePath.substring(lastIndex + 1);
List<Object> param = new ArrayList<>();
// 查询语句
StringBuilder selectBuilder = new StringBuilder(" select * from " + tableName + " where 1=1");
// 查询条件
StringBuilder whereBuilder = new StringBuilder(); // 拼接共通参数
if (commonParameter != null) {
// 拼接共通参数
Field[] fields = commonParameter.getClass().getDeclaredFields();
for (Field curField : fields) {
// 设置字段可访问(必须,否则报错)
curField.setAccessible(true);
String name = curField.getName();
whereBuilder.append(" and " + name + "=?");
Object vlaue = ReflectionUtil.getVlaue(commonParameter, name, "");
param.add(vlaue);
}
}
// 如果设置了表和特殊参数则按照特殊情况处理,否则使用共通参数拼接条件
if (tableAndParams != null) {
// 遍历该实体对象设置的配置信息
// 获取主表
String table = tableAndParams.getTable(); // 拼接自定义经营范围
Field[] fields = tableAndParams.getClass().getDeclaredFields();
for (Field field : fields) {
// 判断是否为查询条件
if (field.isAnnotationPresent(CustomAnnotation.search.class)) {
whereBuilder.append(" and " + field.getName() + "=?");
Object vlaue = ReflectionUtil.getVlaue(tableAndParams, field.getName(), "");
param.add(vlaue);
} // 关联查询
if (field.isAnnotationPresent(CustomAnnotation.connectSearchTerm.class)) {
String name = field.getName();
String values = GsUtils.blankNull(ReflectionUtil.getVlaue(tableAndParams, name, ""));
String[] split = values.split(",");
String sideWhere = "";
for (int i = 0; i < split.length; i++) { sideWhere += " and " + name + " in(";
sideWhere += "'" + split[i] + "'" + ",";
}
;
sideWhere = sideWhere.substring(0, sideWhere.length() - 1);
sideWhere += " )"; whereBuilder.append(sideWhere);
}
} }
// 获取查询对象的class对象
Class tableClazz = Class.forName(tablePath);
// hql不为空和hql中不包含and符号时,禁止执行sql,防止全库扫描
if (StringUtils.isEmpty(whereBuilder.toString())) {
throw new Exception("hql错误,因不存在and查询条件,会导致全库扫描" + selectBuilder.toString());
}
// TODO 执行sql 将查询到数据封装到list<bean>对象中
// List list = baseDao.findByHql(selectBuilder.toString()+whereBuilder.toString(),tableClazz,param);
// TODO 这段代码为无用的为获取数据的代码
List list = findDataInfo(tableName,whereBuilder,param);
// 将查询到的信息添加到传输文件实体对象中
if (list != null && list.size() > 0) {
obj = ReflectionUtil.setValue(obj, clazz, tableName, list);
} // 连表查询
if (sideTablePath != null) {
String sideTableName = Class.forName(sideTablePath).getSimpleName();
// 获取该实体对象设置的自定义信息
TableAndParamsDTO sideTableAndParams = tableAndParamsList.stream().filter(o -> o.getTable().equals(sideTableName)).findAny().orElse(null);
// 拼接自定义经营范围
Field[] sideFields = sideTableAndParams.getClass().getDeclaredFields();
for (Field field : sideFields) {
// 关联查询
if (field.isAnnotationPresent(CustomAnnotation.connectSearchTerm.class)) {
String term = field.getAnnotation(CustomAnnotation.connectSearchTerm.class).term();
String sideParam = "";
for (Object obj1 : list) {
Object value = ReflectionUtil.getVlaue(obj1, (String) term, "");
if (value != null) {
sideParam += value + ",";
}
}
if (StringUtils.isEmpty(sideParam)) {
throw new Exception("关联表但为获取到关联条件信息" + selectBuilder.toString());
}
// 将值设置到对象中
field.setAccessible(true);
field.set(sideTableAndParams, sideParam);
}
}
// 拼接hql和执行获取数据
obj = connectSqlAndExexute(obj, clazz, sideTablePath, sideTableAndParams, null);
}
System.out.println("tableAndParams:" + tableAndParams + "commonParams:" + commonParameter + "执行sql语句:" + selectBuilder.toString() + whereBuilder.toString() + "查询条件:" + param + "查询结果:" + list);
return obj;
} private static List findDataInfo(String tableName, StringBuilder whereBuilder, List<Object> param) {
List<Object> list = new ArrayList<Object>();
if("Cat".equals(tableName)){
list.add(catList.get(0));
return list;
}
if("Dog".equals(tableName)){
list.add(dogList.get(0));
return list;
}
return list;
}
}

执行完成之后,就可以获取到咱们需要的数据了。

4.获取到数据后,发送给另一端,进行解析保存

/**
* 保存待处理数据
*
* @param obj
*/
@Override
public void saveOtherInfo(Object obj) throws Exception {
// 首先得到pojo所定义的字段
Field[] fields = obj.getClass().getDeclaredFields();
for (Field curField : fields) {
// 设置字段可访问(必须,否则报错)
curField.setAccessible(true); Class<?> curFieldType = curField.getType();
// 集合List元素
if (curFieldType.equals(List.class)) {
// 当前集合的泛型类型
Type genericType = curField.getGenericType();
if (null == genericType) {
continue;
}
if (genericType instanceof ParameterizedType) {
Object object = ReflectionUtil.getVlaue(obj,(String) curField.getName(),"");
if(object!=null){
List list = (List)object;
for (int i=0;i<list.size();i++){
Object o = list.get(i);
// baseDao.saveOrUpdate(o);
}
}
}
}else{
System.out.println((curField.getName() + "--暂不支持的类型--" + curFieldType.getSimpleName()));
}
}
}

这样两端进行数据传输就完成了,或中间使用消息中间件进行传输也是可以的。

对于上面的有什么不懂或者有疑问的可以联系qq:1197852132

利用实体bean对象批量数据传输处理的更多相关文章

  1. 把实体bean对象转换成DBObject工具类

    import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util ...

  2. Java—JSON串转换成实体Bean对象模板

    介绍 模板需求说明   开发中经常遇到前端传递过来的JSON串的转换,后端需要解析成对象,有解析成List的,也有解析成Map的. 依赖 <dependency> <groupId& ...

  3. 持久化API(JPA)系列(三)实体Bean的开发技术-建立与数据库的连接

    在EJB 2.x中.EJB有3种类型的Bean.各自是会话Bean(Session Bean).消息驱动Bean(Message-Driven Bean)和实体Bean(Entity Bean). 随 ...

  4. mongodb中Gson和java##Bean对象转化类

    此类使用感觉比较繁琐, 每个字段加注解才可以使用, 不如mongoTemplate使用方便, 但如果使用mongo客户端的话, 还是比手动拼接快一点, 所以贴在这儿 package com.iwher ...

  5. spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象

    相关 知识 >>> 相关 练习 >>> 实现要求: 在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXm ...

  6. 谈谈序列化—实体bean一定要实现Serializable接口?

    导读:最近在做项目的过程中,发现一个问题,就是我们最开始的时候,传递参数包括返回类型,都有map类型.但是由于map每次都要匹配key值,很麻烦.所以在之后就将参数传递和返回类型全都改成了实体bean ...

  7. 【道德经】漫谈实体、对象、DTO及AutoMapper的使用

    写在前面 实体和值对象 实体和对象 故常无欲以观其妙,常有欲以观其徼 初始实体和演化实体 代码中的DTO AutoMapper实体转换 后记 实体(Entity).对象(Object).DTO(Dat ...

  8. 简单模拟Spring管理Bean对象

    1: 首先我们要利用dom4j进行xml的解析,将所有的bean的配置读取出来. 2:利用java的反射机制进行对象的实例化. 3: 直接获得对象 package cn.Junit.test; imp ...

  9. .NET 利用反射将对象数据添加到数据库

    .NET 利用反射将对象数据添加到数据库   一些小型的项目,在不使用其他的框架(LINQ,NHibernate,EF等等框架)的前提下,这时候一些反复的增删改查就会让我们感到极其的繁琐,厌烦,为了避 ...

随机推荐

  1. 攻防世界 reverser secret-galaxy-300

    secret-galaxy-300 school-ctf-winter-2015 运行程序 完全没有flag的身影呀 ida查看字符串 也没有相关信息 动态调试,看运行后内存信息 发现了一串字符 al ...

  2. 总结下js排序算法和乱序算法

    其实本人最怕的就是算法,大学算法课就感觉老师在讲天书,而且对于前端来说,算法在实际的应用中实在是很有限.毕竟算法要依靠大量的数据为基础才能发挥出算法的效率,就浏览器那性能,......是吧,退一万步说 ...

  3. SSM 电影后台管理项目

    SSM 电影后台管理项目 概述 通过对数据库中一张表的CRUD,将相应的操作结果渲染到页面上. 笔者通过这篇博客还原了项目(当然有一些隐藏的坑),然后将该项目上传到了Github.Gitee,在末尾会 ...

  4. 论Redis分布式锁的正确使用姿势

    前言 日常开发中,秒杀下单.抢红包等等业务场景,都需要用到分布式锁.而Redis非常适合作为分布式锁使用.本文将分七个方案展开,跟大家探讨Redis分布式锁的正确使用方式.如果有不正确的地方,欢迎大家 ...

  5. Java中的三大特性 - 超详细篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的三大特性 - 超详细篇>,希望对大家有帮助,谢谢 这一节的内容可能有点多,大家可以选择性的来看 简介 Java的三大特性:封装.继 ...

  6. [矩阵乘法] PKU3233 Matrix Power Series

    [ 矩 阵 乘 法 ] M a t r i x P o w e r S e r i e s [矩阵乘法]Matrix Power Series [矩阵乘法]MatrixPowerSeries Desc ...

  7. Scrapy框架的安装

    Win+R 输入cmd打开命令行 我们先把pip升级到最新版,输入代码如下: pip install --upgrade pip 不过一般这种更新方式会经常性出错,安装文件在下载到一半时就会超时报错 ...

  8. 随便聊聊 Java 8 的函数式编程

    函数式编程(Functional Programming) 首先,我们来了解一个叫做"编程范式"的概念. 什么是"编程范式"呢?简单来说就是指导我们编程的方法论 ...

  9. OOUnit2Summary

    一.前三次作业内容分析 前言 第二单元的作业以多线程为主题,以电梯调度为背景,分三次要求逐步增加,难度逐步提高.这三次作业,更新了我对于面向对象编程的认知,也进一步提高了我编程和调试的能力. 一下是我 ...

  10. (十八)VMware Harbor 镜像同步

    为什么需要镜像同步 由于对镜像的访问是一个核心的容器概念,在实际使用过程中,一个镜像库可能是不够用的,下例情况下,我们可能会需要部署多个镜像仓库: 国外的公有镜像下载过慢,需要一个中转仓库进行加速 容 ...