Java实现同步枚举类数据到数据库

本文实例为大家分享了Java同步枚举类数据到数据库的具体实现代码,供大家参考,具体内容如下

1.需求说明:

我们在开发中常常会用到数据字典,后端程序中也会经常用到(一般是用枚举类来存储),然而我们数据库中也会维护一个数据字典的数据,便于前端做数据显示时的处理,有一个问题就是,如果字典项发生变化后,我们需要修改枚举类和数据库的字典数据,要修改两次,还要面临二者不一致的风险。

所以这里的一个决绝方案就是自动读取枚举类的数据并更新到数据库,本文只讲枚举类数据的提取。

2.首先创建一个描述枚举类型的注解:

package com.visy.enums2dict.annotations;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnumDesc {
    String value();
}

3.创建一个枚举类接口,以规范枚举类

package com.visy.enums2dict.interfaces;

public interface EnumInterface {

    String getCode();

    String getName();

    String getRemark();

    /**
     * 通过代码获取名称
     */
    String getNameByCode(String code);
}

4.创建保存枚举数据的实体

package com.visy.enums2dict.core;

public class DictEntity {
    private String typeCode;
    private String typeName;
    private String code;
    private String name;
    private String remark;

    DictEntity(){}

    DictEntity(String code, String name, String remark){
        this.code = code;
        this.name = name;
        this.remark = remark;
    }
    DictEntity(String typeCode, String code, String name, String remark){
        this.typeCode = typeCode;
        this.code = code;
        this.name = name;
        this.remark = remark;
    }
    DictEntity(String typeCode, String typeName, String code, String name, String remark){
        this.typeCode = typeCode;
        this.typeName = typeName;
        this.code = code;
        this.name = name;
        this.remark = remark;
    }

    public void setTypeCode(String typeCode) {
        this.typeCode = typeCode;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public String getTypeCode() {
        return typeCode;
    }

    public String getTypeName() {
        return typeName;
    }

    public String getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    public String getRemark() {
        return remark;
    }

    public String toString(){
        return "typeCode="+this.getTypeCode()+",typeName="+this.getTypeName()+",code="+this.getCode()+",name="+this.getName()+",remark="+this.getRemark();
    }
}

5.提取枚举数据的核心类

package com.visy.enums2dict.core;

import com.visy.enums2dict.annotations.EnumDesc;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class EnumsToDict {

    //获取指定包下的所有类路径
    private static List<String> getClassesByPackage(String packagePath) {
        //获取包的文件路径
        String basePath = ClassLoader.getSystemResource("").getPath();
        String filePath = basePath + packagePath.replace(".", "/");

        //获取包下所有类路径
        List<String> classPathList = new ArrayList<String>();
        getClassPaths(filePath, classPathList);

        return classPathList;
    }

    private static void getClassPaths(String rootPath, List<String> result){
        File rootFile = new File(rootPath);
        File[] children = rootFile.listFiles();
        if(children==null){
            result.add(classPathPickUp(rootFile.getPath()));
            return;
        }
        for(File child: children){
            String childPath = child.getPath();
            if(child.isDirectory()){
                getClassPaths(childPath, result);
            }else{
                result.add(classPathPickUp(childPath));
            }
        }
    }

    //从文件路径提取类路径
    private static String classPathPickUp(String filePath){
        if(filePath!=null && !"".equals(filePath)){
            int start = filePath.indexOf("classes");
            int end = filePath.indexOf(".class");
            String classPath = filePath.substring(start,end).replace("\\",".");
            return classPath.replace("classes.","");
        }
        return filePath;
    }

    //获取指定枚举类的全部数据
    private static List<DictEntity>  getDataByClass(String classPath){
        List<DictEntity> dictList = new ArrayList<DictEntity>();
        try{
            Class<?> clazz = Class.forName(classPath);
            Object[] values = clazz.getEnumConstants();

            EnumDesc enumDesc =  clazz.getAnnotation(EnumDesc.class);
            String typeName = enumDesc!=null ? enumDesc.value() : null;

            Method m1 = clazz.getDeclaredMethod("getCode");
            Method m2 = clazz.getDeclaredMethod("getName");
            Method m3 = clazz.getDeclaredMethod("getRemark");
            Method.setAccessible(new Method[]{m1,m2,m3},true);

            for(Object value: values){
                String typeCode = value.getClass().getSimpleName();
                String code = (String)m1.invoke(value);
                String name = (String)m2.invoke(value);
                String remark = (String)m3.invoke(value);
                DictEntity dict = new DictEntity(typeCode,typeName,code,name,remark);
                dictList.add(dict);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        return dictList;
    }

    //获取指定包下所有枚举配置数据
    public static List<DictEntity> getDictsOfPackage(String pkgPath) {
        List<String> list = getClassesByPackage(pkgPath);
        List<DictEntity> dictList = new ArrayList<DictEntity>();
        for(String path: list){
            dictList.addAll(getDataByClass(path));
        }
        return dictList;
    }
}

6.准备两个枚举类(需实现2中的接口和1的注解)

package com.visy.enums2dict.enums;

import com.visy.enums2dict.annotations.EnumDesc;
import com.visy.enums2dict.interfaces.EnumInterface;

@EnumDesc("入库单状态")
public enum InbStatus implements EnumInterface {
    CREATE("100","新建"),
    PALLET_FINISH("260","码盘完成"),
    PART_FINISH("300", "部分完成"),
    FULL_FINISH("310","全部完成"),
    CLOSE("950", "关闭"),
    CANCEL("999", "取消");

    private String code;
    private String name;
    private String remark;

    InbStatus(String code, String name){
        this.code = code;
        this.name = name;
    }

    InbStatus(String code, String name, String remark){
        this.code = code;
        this.name = name;
        this.remark = remark;
    }

    public String getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    public String getRemark() {
        return remark;
    }

    public String getNameByCode(String code){
        for(InbStatus status : InbStatus.values()){
            if(code!=null && code.equals(status.getCode())){
                return status.getName();
            }
        }
        return null;
    }
}
package com.visy.enums2dict.enums;

import com.visy.enums2dict.annotations.EnumDesc;
import com.visy.enums2dict.interfaces.EnumInterface;

@EnumDesc("出库单订单状态")
public enum OubStatus implements EnumInterface {
    ALL_ALLOCATE("300","全部分配"),
    PART_JH("320","部分拣货");

    private String code;
    private String name;
    private String remark;

    OubStatus(String code, String name){
        this.code = code;
        this.name = name;
    }

    OubStatus(String code, String name, String remark){
        this.code = code;
        this.name = name;
        this.remark = remark;
    }

    public String getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    public String getRemark() {
        return remark;
    }

    public String getNameByCode(String code){
        for(InbStatus status : InbStatus.values()){
            if(code!=null && code.equals(status.getCode())){
                return status.getName();
            }
        }
        return null;
    }
}

7.测试:

package com.visy.enums2dict.test;

import com.visy.enums2dict.core.DictEntity;
import com.visy.enums2dict.core.EnumsToDict;

import java.util.List;

public class EnumsToDictTest {
    public static void main(String[] args) {
        List<DictEntity> dictList = EnumsToDict.getDictsOfPackage("com.visy.enums2dict.enums");
        for(DictEntity dict: dictList){
            System.out.println(dict.toString());
        }
    }
}

8.输出结果:

typeCode=InbStatus,typeName=入库单状态,code=100,name=新建,remark=null
typeCode=InbStatus,typeName=入库单状态,code=260,name=码盘完成,remark=null
typeCode=InbStatus,typeName=入库单状态,code=300,name=部分完成,remark=null
typeCode=InbStatus,typeName=入库单状态,code=310,name=全部完成,remark=null
typeCode=InbStatus,typeName=入库单状态,code=950,name=关闭,remark=null
typeCode=InbStatus,typeName=入库单状态,code=999,name=取消,remark=null
typeCode=OubStatus,typeName=出库单订单状态,code=300,name=全部分配,remark=null
typeCode=OubStatus,typeName=出库单订单状态,code=320,name=部分拣货,remark=null

然后,你就可以将这些数据同步到数据库啦

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2022-08-09

基于Java方式实现数据同步

本文实例为大家分享了Java方式实现数据同步的具体代码,供大家参考,具体内容如下 使用java方式实现两个系统之间数据的同步. 业务背景 在新系统中设置定时任务需要实时把客户系统中的数据及时同步过来,保持数据的一致性. 实现逻辑 1.根据客户提供的接口,本系统中采用Http的Post请求方式获取接口数据.2.由于客户提供的接口必带页码和页面容量,因此会涉及到多次请求接口才能拿到全量数据,因此相同的操作可以采用递归的方式进行.3.每次请求一次接口根据页面容量(pageSize)可获取多条数据,此时

Java实现多线程大批量同步数据(分页)

背景 最近遇到个功能,两个月有300w+的数据,之后还在累加,因一开始该数据就全部存储在mysql表,现需要展示在页面,还需要关联另一张表的数据,而且产品要求页面的查询条件多达20个条件,最终,这个功能卡的要死,基本查不出来数据. 最后是打算把这两张表的数据同时存储到MongoDB中去,以提高查询效率. 一开始同步的时候,采用单线程,循环以分页的模式去同步这两张表数据,结果是…一晚上,只同步了30w数据,特慢!!! 最后,改造了一番,2小时,就成功同步了300w+数据. 以下是主要逻辑. 线程的

java 定时同步数据的任务优化

前言 定时任务在系统中并不少见,主要目的是用于需要定时处理数据或者执行某个操作的情况下,如定时关闭订单,或者定时备份.而常见的定时任务分为2种,第一种:固定时间执行,如:每分钟执行一次,每天执行一次.第二种:延时多久执行,就是当发生一件事情后,根据这件时间发生的时间定时多久后执行任务,如:15分钟后关闭订单付款状态,24小时候后关闭订单并且释放库存,而由于第二种一般都是单一数据的处理(主要是指数据量不大,一般情况下只有一个主体处理对象,如:一个订单以及订单中的N个商品),所以一般情况下第二种出现

java多线程编程之为什么要进行数据同步

Java中的变量分为两类:局部变量和类变量.局部变量是指在方法内定义的变量,如在run方法中定义的变量.对于这些变量来说,并不存在线程之间共享的问题.因此,它们不需要进行数据同步.类变量是在类中定义的变量,作用域是整个类.这类变量可以被多个线程共享.因此,我们需要对这类变量进行数据同步.数据同步就是指在同一时间,只能由一个线程来访问被同步的类变量,当前线程访问完这些变量后,其他线程才能继续访问.这里说的访问是指有写操作的访问,如果所有访问类变量的线程都是读操作,一般是不需要数据同步的.那么如果不

Java多线程编程实战之模拟大量数据同步

背景 最近对于 Java 多线程做了一段时间的学习,笔者一直认为,学习东西就是要应用到实际的业务需求中的.否则要么无法深入理解,要么硬生生地套用技术只是达到炫技的效果. 不过笔者仍旧认为自己对于多线程掌握不够熟练,不敢轻易应用到生产代码中.这就按照平时工作中遇到的实际问题,脑补了一个很可能存在的业务场景: 已知某公司管理着 1000 个微信服务号,每个服务号有 1w ~ 50w 粉丝不等.假设该公司每天都需要将所有微信服务号的粉丝数据通过调用微信 API 的方式更新到本地数据库. 需求分析 对此

Java多线程编程小实例模拟停车场系统

下面分享的是一个Java多线程模拟停车场系统的小实例(Java的应用还是很广泛的,哈哈),具体代码如下: Park类 public class Park { boolean []park=new boolean[3]; public boolean equals() { return true; } } Car: public class Car { private String number; private int position=0; public Car(String number)

java多线程编程之向线程传递数据的三种方法

在传统的同步开发模式下,当我们调用一个函数时,通过这个函数的参数将数据传入,并通过这个函数的返回值来返回最终的计算结果.但在多线程的异步开发模式下,数据的传递和返回和同步开发模式有很大的区别.由于线程的运行和结束是不可预料的,因此,在传递和返回数据时就无法象函数一样通过函数参数和return语句来返回数据.本文就以上原因介绍了几种用于向线程传递数据的方法,在下一篇文章中将介绍从线程中返回数据的方法. 欲先取之,必先予之.一般在使用线程时都需要有一些初始化数据,然后线程利用这些数据进行加工处理,并

java多线程编程之从线程返回数据的两种方法

一.通过类变量和方法返回数据 使用这种方法返回数据需要在调用start方法后才能通过类变量或方法得到数据.让我们先来看看例程2-13会得到什么结果. 复制代码 代码如下: package mythread; public class MyThread extends Thread{    private String value1;    private String value2; public void run()    {        value1 = "通过成员变量返回数据"

Java多线程编程之访问共享对象和数据的方法

多个线程访问共享对象和数据的方式有两种情况: 1.每个线程执行的代码相同,例如,卖票:多个窗口同时卖这100张票,这100张票需要多个线程共享. 2.每个线程执行的代码不同,例如:设计四个线程,其中两个线程每次对j增加1,另外两个线程每次对j减少1. a.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个对象中有共享数据.卖票就可以这样做,每个窗口都在做卖票任务,卖的票都是同一个数据(点击查看具体案例). b.如果每个线程执行的代码不同,就需要使用不同的Runnable对象,有

Java多线程编程实现socket通信示例代码

流传于网络上有关Java多线程通信的编程实例有很多,这一篇还算比较不错,代码可用.下面看看具体内容. TCP是Tranfer Control Protocol的 简称,是一种面向连接的保证可靠传输的协议.通过TCP协议传输,得到的是一个顺序的无差错的数据流.发送方和接收方的成对的两个socket之间必须建 立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以

java多线程编程学习(线程间通信)

一.概要 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就是成为整体的必用方案之一.可以说,使线程进行通信后,系统之间的交互性会更强大,在大大提高cpu利用率的同时还会使程序员对各线程任务在处理过程中进行有效的把控和监督. 二.等待/通知机制 1."wait/notify"机制:等待/通知机制,wait使线程暂停运行,而notify 使暂停的线程继续运行.用一个厨师和服务员的交互来说明: (1) 服务员取到菜的时间取决于厨师,所以服务员就有&

java多线程编程技术详解和实例代码

 java多线程编程技术详解和实例代码 1.   Java和他的API都可以使用并发. 可以指定程序包含不同的执行线程,每个线程都具有自己的方法调用堆栈和程序计数器,使得线程在与其他线程并发地执行能够共享程序范围内的资源,比如共享内存,这种能力被称为多线程编程(multithreading),在核心的C和C++语言中并不具备这种能力,尽管他们影响了JAVA的设计. 2.   线程的生命周期 新线程的生命周期从"新生"状态开始.程序启动线程前,线程一直是"新生"状态:

java多线程编程实例

一.相关知识: Java多线程程序设计到的知识: (一)对同一个数量进行操作 (二)对同一个对象进行操作 (三)回调方法使用 (四)线程同步,死锁问题 (五)线程通信 等等 二.示例一:三个售票窗口同时出售20张票; 程序分析: 1.票数要使用同一个静态值 2.为保证不会出现卖出同一个票数,要java多线程同步锁. 设计思路: 1.创建一个站台类Station,继承Thread,重写run方法,在run方法里面执行售票操作!售票要使用同步锁:即有一个站台卖这张票时,其他站台要等这张票卖完! 2.