>  기사  >  Java  >  Java를 기반으로 데이터 동기화를 달성하는 방법

Java를 기반으로 데이터 동기화를 달성하는 방법

王林
王林앞으로
2023-04-28 11:31:062091검색

사업 배경

새로운 시스템에서 예정된 작업을 설정하려면 데이터 일관성을 유지하기 위해 고객 시스템의 데이터를 실시간으로 동기화해야 합니다.

구현 로직

1. 이 시스템은 고객이 제공한 인터페이스에 따라 Http Post 요청 방식을 사용하여 인터페이스 데이터를 얻습니다.
2. 고객이 제공하는 인터페이스에는 페이지 번호와 페이지 용량이 있어야 하므로 전체 데이터 양을 얻으려면 인터페이스에 대한 여러 요청이 필요하므로 동일한 작업이 반복적으로 수행될 수 있습니다.
3. 인터페이스를 요청할 때마다 페이지 용량(pageSize)을 기준으로 여러 데이터를 얻을 수 있으며 이때 데이터베이스를 일괄 추가하고 일괄 SQL을 사용하여 명령문을 추가할 수 있습니다.
4. 데이터 동기화는 두 시스템 간의 데이터 일관성을 유지해야 하므로 예약된 작업을 사용하고 동기화 빈도를 지정해야 합니다(예: 하루에 한 번 또는 하루에 두 번).
5. 예약된 작업을 사용하면 데이터 중복 문제가 발생할 수 있으므로, 데이터가 반복적으로 추가되는 문제를 방지하기 위해 고유한 필드를 기반으로 고유한 인덱스를 설정합니다.
6. 고유 인덱스를 설정하면 동일한 레코드가 반복해서 추가되는 문제는 피할 수 있지만, 고유 인덱스 필드를 제외한 동일한 레코드 내 다른 필드의 해당 데이터가 변경되는 문제는 피할 수 없습니다. SQL 문을 추가하면 이 문제를 해결할 수 있습니다.

팁: a. 이 데이터 행이 테이블에 이미 존재하는 경우(기본 키 또는 고유 인덱스를 기준으로 판단) 먼저 이 데이터 행을 삭제한 다음 새 데이터를 삽입하세요. b. 그렇지 않으면 새 데이터를 직접 삽입하십시오.

기술 사용

1. 예약된 작업을 설정하세요.
2. 인터페이스 데이터를 얻으려면 Http의 Post 메서드를 사용하세요.
3. 여러 페이지의 데이터가 포함된 경우 재귀 루프 호출이 사용됩니다.
4. 일괄 작업 데이터베이스(교체).
5. 반복적인 데이터 삽입을 방지하려면 고유한 인덱스를 만드세요.

코드 세부정보

1.StudentMapper.java

/**
     * 批量添加数据同步接口学生数据
     * @param studentList
     * @return
     */
    int addBatchStudent(@Param(value = "studentList") List<Student> studentList);

2.SyncStudentServiceImpl.java 코드는 다음과 같습니다.

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import ***.common.utils.HttpUtils;
import ***.common.utils.StringUtils;
import ***.entity.sync.Student;
import ***.mapper.sync.StudentMapper;
import ***.service.sync.SyncStudentService;
import ***.vo.StudentVO;
import lombok.extern.slf4j.Slf4j;

/**
 * 数据同步的学生实现类
 * @author hc
 * @create 2021/03/25 11:20
 * @version 1.0
 * @since 1.0
 */
@Service
@Slf4j
public class SyncStudentServiceImpl implements SyncStudentService {
    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private HttpUtils httpUtils;

    @Override
    public void bulkAddStudent(StudentVO studentVO) {
        log.info("调取学生接口传的参数对象studentVO:"+studentVO);
        log.info("开始调取学生接口获取第" + studentVO.getPageIndex() + "页数据");
        //如何页面容量小于100,则按100计算
        if(studentVO.getPageSize() < 100) {
            studentVO.setPageSize(100);
        }
        //根据当前页码和页面容量调取获取学生数据接口
        JSONObject jsonObject = this.sendStudentHttpPost(studentVO);
        //判断返回JSONObject是否为null
        if (StringUtils.isNotNull(jsonObject) && jsonObject.containsKey("errcode") && jsonObject.getInteger("errcode") == 0) {
            if(jsonObject.containsKey("data")){
                JSONArray jsonArray = jsonObject.getJSONArray("data");
                //通过判断获取的jsonObject对象中key值为data是否为null和其 jsonArray的长度来判断是否进行递归
                //提示:此判断方法好于通过计算总页码的方式来递归拿数据(对获取的total依赖过大,因此放弃此方式)
                if(jsonObject.getString("data") != null && jsonArray.size() > 0) {
                   log.info("当前数据加载到几页》》》》:{}", studentVO.getPageIndex());
                   //调取批量添加数据
                   this.addStudentCycleData(jsonObject, studentVO);
                   //页码加1,继续调取下一页数据
                      studentVO.setPageIndex(studentVO.getPageIndex() + 1);
                     //采用递归方式直至循环结束
                   this.bulkAddStudent(studentVO);
                }else {
                    log.info("学生数据同步结束》》》");
                }
            }
        }
    }

    /**
     * 批量添加学生数据
     * @param jsonObject
     * @param areaVO
     * @return
     */
    public void addStudentCycleData(JSONObject jsonObject, StudentVO studentVO){
        List<Student> studentList = null;
        //判断jsonArray时候为空
        if (jsonObject != null && StringUtils.isNotBlank(jsonObject.getString("data"))) {
            //把JsonArray转成对应实体类集合
            studentList = JSONObject.parseArray(jsonObject.getString("data"), Student.class);
        }
        try {
            log.info("学生接口第" + studentVO.getPageIndex() + "页数据开始入库...");
            //调取方法批量进行添加学生数据
            studentMapper.addBatchStudent(studentList);
            log.info("学生接口第" + studentVO.getPageIndex() + "页数据入库成功...");
        } catch (Exception e) {
            log.error("学生批量添加数据库异常:{}", e.getMessage());
        }
    }

    /**
     * 根据studentVO(当前页码和页面容量)发送获取学生数据的请求
     * @param studentVO
     * @return
     */
    public JSONObject sendStudentHttpPost(StudentVO studentVO){
        JSONObject jsonObject = null;
        String studentUrl = "http://*****/async-api/jc/student";
        try {
            if (StringUtils.isNotEmpty(studentUrl)) {
                Map<String, Object> param = new HashMap<>();
                param.put("pageIndex", studentVO.getPageIndex());
                param.put("pageSize", studentVO.getPageSize());
                log.info("开始发起http请求...");
                jsonObject = httpUtils.sendHttpPost(param, studentUrl);
            }
        } catch (Exception e) {
            log.error("调取客户学生同步接口出现异常:{},页面容量为:{},页码:{}", e.getMessage(), 
            studentVO.getPageSize(), studentVO.getPageIndex());
        }
        return jsonObject;
    }
}

3.StudentVO.java 코드는 다음과 같습니다.

import lombok.Data;
/**
 * 数据同步接口获取学生数据传的参数VO类
 * @author hc
 * @create 2021/3/11 10:35
 * @version 1.0
 * @since 1.0
 */
@Data
public class StudentVO{
    //当前页码(初始值为0)
    private Integer pageIndex = 0;
    //页码容量
    private Integer pageSize;
}

4.HttpUtils.java 코드는 다음과 같습니다.

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.util.Map;

/**
 * Http请求工具类
 * @author hc
 * @create 2021/3/4
 * @version 1.0
 */
@Component
@Slf4j
public class HttpUtils {
    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * 发送http的post请求方法
     * @param param
     * @return
     */
    public JSONObject sendHttpPost(Integer type, Map<String, Object> param, String url){
        log.info("调取同步接口Url:{}", url);
        JSONObject jsonObject = null;
        //发起http的post准备工作
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(param, httpHeaders);
        ResponseEntity<String> response = null;
        try {
            log.info("param参数为:{}",param.toString());
            response = restTemplate.postForEntity(url, httpEntity, String.class);
        } catch (HttpClientErrorException e) {
            log.error("发起http请求报错信息:{}",e.getResponseBodyAsString());
        }
        String bodyData = response.getBody();
        if (StringUtils.isNotEmpty(bodyData)) {
            jsonObject = JSONObject.parseObject(bodyData);
        }
        return jsonObject;
    }
}

5.StudentMapper .xml의 SQL 문은 다음과 같습니다.

<!-- 批量添加数据同步接口中获取的学生数据 -->
<insert id="addBatchStudent" parameterType="***.entity.sync.Student">
    replace into xf_clue_sync_student(id, student_code, student_name, status, create_date, update_date)
    <foreach collection="studentList" item="student" open="values" separator="," >
       (#{student.id,jdbcType=BIGINT}, #{student.studentCode,jdbcType=INTEGER}, #{student.studentName,jdbcType=VARCHAR}, 
        #{student.status,jdbcType=INTEGER}, #{student.createDate,jdbcType=VARCHAR}, #{student.updateDate,jdbcType=VARCHAR})
    </foreach>
</insert>

Function summary

1 예약된 작업 구성과 관련된 코드는 더 이상 여기에 표시되지 않습니다. SpringBoot 프레임워크는 예약된 작업 및 호출 빈도를 설정하는 데 더 이상 표시되지 않습니다.
2. 데이터 동기화 인터페이스를 개발하려면 상황에 따라 특정 애플리케이션 시나리오에 따라 다양한 방법이 필요합니다. 예를 들어 주전자 도구 등을 사용할 수도 있습니다.

위 내용은 Java를 기반으로 데이터 동기화를 달성하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제