데이터 이전 - 데 이 터 를 SQLServer 에서 PostgreSQL 로 이전 합 니 다.

144535 단어 데이터 구조
글 목록
  • 개발 배경
  • 수요 배경
  • 분석 해결
  • 데이터 뱅 크 의 서로 다른 소스 문 제 를 해결 합 니 다
  • 데이터 양 이 너무 많은 문제 해결
  • 읽 기보 다 쓰기 가 느 린 문제 해결
  • 메 인 키 충돌 문제 해결
  • 소스 코드
  • 핵심 의존
  • Java 소스 코드
  • 도구 류
  • 유 니 버 설 모듈
  • 실체 류
  • Feign 원 격 호출
  • SQLServer
  • 데이터 변환
  • 변환 함수 호출
  • repository
  • service
  • controller
  • Bootstrap 시작 클래스
  • 프로필
  • 운행 결과
  • 개발 배경
    필요 배경
        프로젝트 재 구성 수요 로 인해 현재 데 이 터 를 SQLServer 에서 PostgreSQL 로 옮 깁 니 다. 원래 프로젝트 는 단일 프로젝트 (즉, 프로젝트 표 에 영원히 하나의 데이터 만 있 음) 이기 때문에 현재 여러 프로젝트 를 하나의 데이터 베이스 로 옮 깁 니 다. 그러면 프로젝트 표 에 여러 프로젝트 가 나타 납 니 다 (이때 id 는 반드시 충돌 합 니 다).
    분석 하여 해결 하 다
    데이터베이스 의 다른 소스 문 제 를 해결 하 다.
    * 8195: 8195: 이때 의 데이터 이전 은 하나의 데이터 베이스 에서 다른 같은 데이터 베이스 형식의 다른 데이터 베이스 로 이전 하 는 것 이 아니 라 SQLServer 에서 PostgreSQL 로 이전 하기 때 문 입 니 다 (데이터 베 이 스 는 서로 다른 소스).이때 우리 가 먼저 직면 한 것 은 데이터베이스 가 서로 다른 표 구조 문장의 차이성 문제 이다.
    이 문 제 를 해결 하기 위해 저 는 다음 과 같은 해결 방안 을 찾 았 습 니 다.
  • JPA 를 사용 하여 하 이 버 네 이 트 의 JPA 를 사용 하여 데이터베이스 바 텀 의 차이 점 을 차단 함으로써 이들 데이터베이스 가 서로 다른 데이터 조작 문 제 를 해결 합 니 다.
  • 읽 기와 쓰기 분리의 실현 방안 을 채택 하여 이 실현 을 두 개의 서로 독립 된 마이크로 서비스 모듈 로 나 누 었 는데 각각 spring-sqlserverspring-postgresql 이다.전 자 는 데이터 읽 기 (SQLServer 에서) 에 만 사용 되 고 후 자 는 데이터 쓰기 (PostgreSQL 에서) 에 만 사 용 됩 니 다.

  •     비고, 여기 spring-sqlserver 는 앞의 글 에서 데이터 시트 의 파일 바이트 흐름 을 읽 는 것 을 말 하기 때문에 spring-sqlserver 모듈 과 관련 된 소스 코드 는 앞의 글 에서 직접 표시 되 지 않 습 니 다.
    데이터 양 이 너무 많은 문 제 를 해결 하 다.
        가 져 와 야 할 데이터 의 양 이 많 고 약 30G 이기 때문에 저 는 예전 과 똑 같은 페이지 조회 전략 을 사 용 했 습 니 다. 여기 서 저 희 는 설정 파일 을 통 해 페이지 별로 조회 하 는 정보 항목 수 를 수 동 으로 설정 할 수 있 습 니 다. 여기 서 저 는 100 개 로 설정 되 었 습 니 다. 즉, 매번 spring-sqlserver 에서 100 개의 정 보 를 읽 고 JPA 를 통 해 대량으로 spring-postgresql 에 삽입 한 것 입 니 다.표 의 모든 정 보 를 다 옮 겨 다 닐 때 까지.
    읽 기보 다 쓰기 가 느 린 문 제 를 해결 합 니 다.
        읽 기보 다 쓰기 가 느 린 문 제 를 해결 하기 위해 저 는 Fixed ThreadPool 스 레 드 풀 스 레 드 풀 을 사용 합 니 다. 수 동 으로 스 레 드 를 설정 합 니 다 (테스트 에서 10 개의 스 레 드 를 사 용 했 습 니 다). 하지만 스 레 드 풀 을 사용 하지 않 는 방법 을 작 성 했 습 니 다.
    다시 말 하면 저 는 모두 두 가지 방안 이 있 습 니 다. 하 나 는 스 레 드 탱크 를 사용 하고 다른 하 나 는 스 레 드 탱크 를 사용 하지 않 습 니 다.
        여기 서 주의해 야 할 것 은 Fixed ThreadPool 의 고정 적 인 결함 때문이다. 즉, 내 가 활성 화 된 스 레 드 수량 을 2 로 설정 하면 현재 활성 화 된 스 레 드 수량 은 확실히 2 이지 만 그 스 레 드 총 수 는 2 가 아니 라 전체 스 레 드 풀 을 차지 하 는 것 이다.다시 말 하면 남 은 스 레 드 는 온라인 스 레 드 풀 에서 줄 을 서서 실행 할 때 까지 큰 문제 가 존재 한 다 는 것 이다. 바로 Feign 의 호출 시간 초과 문제 이다. 즉, spring-postgresql 요청 이 발생 하면 앞의 정보 요청 은 정상적으로 진행 되 지만 뒤의 요청 은 연결 시간 초과 가 발생 한 다 는 것 이다.(시간 이 초 과 될 때 까지 Fixed ThreadPool 스 레 드 풀 스 레 드 풀 에서 계속 기 다 려 달라 고 요청 하기 때 문 입 니 다.) 이 로 인해 후속 모든 요청 이 실패 할 수 있 습 니 다. 따라서 정보 요청 이 완전 하지 않 을 때 까지 Hystrix, ribbon 등 을 가능 한 한 닫 아야 합 니 다. 안전 을 위해 서 는 비 스 레 드 풀 방식 을 추천 합 니 다.
    메 인 키 충돌 문제 해결
    『 8195 』 메 인 키 충돌 문 제 를 해결 하기 위해 저 는 다음 과 같은 방법 을 사 용 했 습 니 다.
  • 새로운 메 인 키 생 성
  •     기 존의 메 인 키 idid_v 로 변경 하고 새로운 메 인 키 id_k 를 생 성 합 니 다.
  • 타임 스탬프 추가
  • 데이터 베 이 스 를 가 져 오 는 것 은 하나의 진행 이기 때문에 우 리 는 모든 표 에 시간 필드 를 추가 하여 현재 이 정보 가 가 져 온 시간 스탬프 를 기록 합 니 다. 그러면 데이터 삽입 에 실패 하면 잘못된 위 치 를 찾 을 수 있 습 니 다.
  • procject Id 필드 추가
  •     항목 마다 추가 할 때 표 마다 procject Id 를 추가 합 니 다. 이 procject Id 도 시간 스탬프 (Long 형식) 입 니 다.이전 타임 스탬프 와 다른 점 은 이전 타임 스탬프 가 모든 정 보 를 가 져 오 는 시간 을 기록 한 것 입 니 다. 즉, 하나의 항목 데이터 가 져 오 면 모든 정 보 를 입력 하 는 시간 스탬프 가 다 를 수 있 습 니 다. procject Id 는 이 항목 이 가 져 오기 시작 할 때 스탬프 를 기록 하고 하나의 항목 데이터 베 이 스 를 확인 합 니 다. 이 시간 스탬프 는 모든 표 의 데이터 에 있 습 니 다.동일 하 게 서로 다른 프로젝트 데이터베이스 버 전 을 구분한다.
    소스 코드
    핵심 의존
    
        
        
            org.springframework.cloud
            spring-cloud-starter-eureka
        
        
        
            org.springframework.cloud
            spring-cloud-starter-ribbon
        
        
        
            org.springframework.cloud
            spring-cloud-starter-hystrix
        
        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
        
            org.postgresql
            postgresql
        
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.1
        
        
        
            org.springframework.cloud
            spring-cloud-starter-feign
        
        
        
            com.squareup.okhttp3
            okhttp
        
    
    

    자바 소스 코드
    도구 클래스
      TimeFormatUtil
    package com.lyc.postgresql.util;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/4/11 16:52
     * @description:         
     **/
    public class TimeFormatUtil {
    
        //     
        private long startTime = 0;
        //     
        private long endTime = 0;
    
        /**
         *   TimeFormatUtil  
         * @return
         */
        public static TimeFormatUtil newTimeFormatUtil(){
            return new TimeFormatUtil();
        }
    
        /**
         *       
         * @return
         */
        public void setStartTime(){
            this.startTime = new Date().getTime();
        }
    
        /**
         *       
         * @return
         */
        public void setEndTime(){
            this.endTime = new Date().getTime();
        }
    
        /**
         *          
         * @return
         */
        public String getSpendTime(){
            //       
            long spendTime = this.endTime - this.startTime;
            //              
            return timeToString(spendTime);
        }
    
        /**
         *  long             
         * @param spendTime     
         * @return
         */
        private String timeToString(long spendTime) {
            //   
            long millis = spendTime % 1000;
            //          
            long secondTemp = spendTime / 1000;
            //  
            long hour = secondTemp / 3600;
            //     
            secondTemp = secondTemp % 3600;
            //  
            long minutes = secondTemp / 60;
            //  
            long second = secondTemp % 60;
            //          
            return "      :" + hour + "  " + minutes + "  " + second + " " + millis + "  ";
        }
    
        /**
         *               
         * @param dateString      
         * @return
         */
        public String toDate(String dateString) throws ParseException {
            Locale localeUS = new Locale("en","US");
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy",localeUS);
            Date date = simpleDateFormat.parse(dateString);
            //2019-03-19 07:14:04
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        }
    
    }
    
    

      FieldFormatUtil
    package com.lyc.postgresql.util;
    
    import com.google.common.collect.Maps;
    import lombok.var;
    
    import java.util.Date;
    import java.util.Map;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/29 11:22
     * @description: Map                  
     **/
    public class FieldFormatUtil {
    
        private final Map<String,Object> map;
        private final DataConvertUtil dataConvertUtil;
    
    
        /**
         * FieldFormatUtil     
         * @param map
         */
        public FieldFormatUtil(Map<String,Object> map) {
            if(null != map) {   //      ,     
                this.map = map;
            } else {  //             
                this.map = Maps.newHashMap();
            }
            dataConvertUtil = DataConvertUtil.newDataConvertUtil();
        }
    
        /**
         *     FieldFormatUtil   
         * @param map
         * @return
         */
        public static FieldFormatUtil newFieldFormatUtil(Map<String,Object> map){
            return new FieldFormatUtil(map);
        }
    
        /**
         *       
         * @param k
         * @return
         */
        public int getInt(String k){
            var obj = this.map.get(k);
            return dataConvertUtil.getInt(obj);
        }
    
        /**
         *   Long   
         * @param k
         * @return
         */
        public Long getLong(String k) {
            var obj = this.map.get(k);
            return dataConvertUtil.getLong(obj);
        }
    
        /**
         *   String   
         * @param k
         * @return
         */
        public String getString(String k) {
            var obj = this.map.get(k);
            return dataConvertUtil.getString(obj);
        }
    
        /**
         *   Double     
         * @param k
         * @return
         */
        public Double getDouble(String k) {
            var obj = this.map.get(k);
            return dataConvertUtil.getDouble(obj);
        }
    
        /**
         *          
         * @param k
         * @return
         */
        public Date getDate(String k) {
            var obj = this.map.get(k);
            return dataConvertUtil.getDate(obj);
        }
    
        /**
         *   double     
         * @param k
         * @return
         */
        public float getFloat(String k) {
            var obj = this.map.get(k);
            return dataConvertUtil.getFloat(obj);
        }
    
    }
    
    

      DataConvertUtil
    package com.lyc.postgresql.util;
    
    import lombok.NoArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.joda.time.DateTime;
    
    import java.util.Date;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/29 11:37
     * @description:         
     **/
    @Slf4j
    @NoArgsConstructor
    public class DataConvertUtil {
    
        /**
         *     DataConvertUtil  
         * @return
         */
        public static DataConvertUtil newDataConvertUtil(){
            return new DataConvertUtil();
        }
    
        /**
         *          
         * @param o
         * @return
         */
        public String getString(Object o){
            String str = String.valueOf(o);
            if("null".equals(str) ){
                return null;
            }
            return String.valueOf(o);
        }
    
        /**
         *          
         * @param o
         * @return
         */
        public Long getLong(Object o){
            return Long.valueOf(String.valueOf(o));
        }
    
        /**
         *       int
         * @return
         */
        public int getInt(Object o){
            String str = String.valueOf(o);
            if("null".equals(str) ){
                return 0;
            }
            return Integer.valueOf(str);
        }
    
        /**
         *       Double    
         * @param o
         * @return
         */
        public double getDouble(Object o){
            return Double.valueOf(String.valueOf(o));
        }
    
        /**
         *       Date
         * @param obj
         * @return
         */
        public Date getDate(Object obj) {
            if(obj instanceof Long){  //    long  
                //       Long    
                Long timeLong = Long.valueOf(String.valueOf(obj));
                //  long        DateTime    
                DateTime dateTime = new DateTime(timeLong);
                //  Long          
                return dateTime.toDate();
            } else {  //           
                return null;
            }
        }
    
        /**
         *       double
         * @param obj
         * @return
         */
        public float getFloat(Object obj) {
            if(obj != null){
                return Float.valueOf(String.valueOf(obj));
            }
            return 0L;
        }
    
    }
    
    

    유 니 버 설 모듈
      CommonConstant
    package com.lyc.postgresql.common;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/4/16 16:07
     * @description:     
     **/
    public class CommonConstant {
    
        public interface TableVersion{
            String PROJECT_ID = "projectId";
        }
    
    }
    
    

      EntityConvert
    package com.lyc.postgresql.common;
    
    import java.util.Map;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/29 11:16
     * @description:        
     **/
    public interface EntityConvert<T> {
    
        T formatToEntity(Map<String,Object> map);
    
    }
    
    

      EntityFunction
    package com.lyc.postgresql.common;
    
    import java.util.Map;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/30 10:26
     * @description:      
     **/
    @FunctionalInterface
    public interface EntityFunction {
    
        EntityModel convertToEntity(Map<String,Object> map);
    
    }
    
    

      EntityModel
    package com.lyc.postgresql.common;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/30 11:17
     * @description:      
     **/
    public class EntityModel {
    }
    
    

      EntityRepository
    package com.lyc.postgresql.common;
    
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/30 9:55
     * @description:           Repository        
     **/
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class EntityRepository {
    
        private String tableName;
        private EntityFunction entityFunction;
        private JpaRepository jpaRepository;
    
    }
    
    

      NumberThreads
    package com.lyc.postgresql.common;
    
    import lombok.*;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/4/2 16:04
     * @description:       
     **/
    @Component
    @Getter
    @Setter
    public class NumberThreads {
    
        //             
        @Value("${thread.numberTreads}")
        private String numberThreads;
        //            
        @Value("${pagequery.cycleTime}")
        private String cycleTime;
    
    }
    
    

    실체 류
      GcFilenum
    package com.lyc.postgresql.entity;
    
    import com.lyc.postgresql.common.EntityModel;
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import java.util.Date;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/4/4 16:05
     * @description:  filenum   
     **/
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Entity
    public class GcFilenum extends EntityModel {
    
        @Id
        @GeneratedValue
        private Long id_k;
        private String id_v;
        private String mid;
        private String topid;
        private String flag;
        private Integer nlevel;
        private String str;
        private String spstr;
        private String content;
        private Date createTime;
        //   id
        private Long projectId;
    
    }
    
    

    생략 하 다.
    Feign 원 격 호출
      ItemFeignClient
    package com.lyc.postgresql.feign;
    
    import org.springframework.cloud.netflix.feign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    import java.util.List;
    import java.util.Map;
    
    /**
     * Feign       
     */
    @FeignClient(value = "sqlserver-server")    //      Feign    
    public interface ItemFeignClient {
    
        /**
         *              
         * @param table
         * @return
         */
        @GetMapping("/countFrom/{table}")
        int countFrom(@PathVariable("table") String table);
    
        /**
         *            
         * @param table   
         * @param sortedField     
         * @param start      
         * @param size         
         */
        @GetMapping("/selectListPageQueryFrom/{table}/{sortedField}/{start}/{size}")
        List<Map<String,Object>> selectListPageQuery(@PathVariable("table") String table, @PathVariable("sortedField") String sortedField, @PathVariable("start") int start, @PathVariable("size") int size);
    
    }
    
    

    SQLServer
      CollectionTables
    package com.lyc.postgresql.sqlServer;
    
    import com.google.common.collect.Lists;
    import com.lyc.postgresql.sqlServer.tables.Tables;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.List;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/29 15:39
     * @description:              ,     List   
     **/
    @Slf4j
    public class CollectionTables {
    
        private final List<Tables> tablesList = Lists.newArrayList();
    
        /**
         *   CollectionTables  
         * @return
         */
        public static CollectionTables newCollectionTables(){
            return new CollectionTables();
        }
    
        public List<Tables> getTables(){
            for(Tables table : Tables.values()){
                log.info("  :{},    :{}",table.getTableName(),table.getSortedField());
                tablesList.add(table);
            }
            return tablesList;
        }
    
    }
    
    

      Tables
    package com.lyc.postgresql.sqlServer.tables;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public enum Tables {
    
        INTERFACE("interface","listId")
        ,FILENUM("filenum","mid")
        ...;
    
        private String tableName;
        private String sortedField;
    
    }
    
    

    데이터 변환
      FilenumConvert
    package com.lyc.postgresql.targetDataConvert;
    
    import com.lyc.postgresql.common.CommonConstant;
    import com.lyc.postgresql.common.EntityConvert;
    import com.lyc.postgresql.entity.GcFilenum;
    import com.lyc.postgresql.util.FieldFormatUtil;
    
    
    import java.util.Date;
    import java.util.Map;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/4/4 16:18
     * @description: Filenum       
     **/
    public class FilenumConvert implements EntityConvert<GcFilenum> {
    
        @Override
        public GcFilenum formatToEntity(Map<String, Object> map) {
    
            FieldFormatUtil field = FieldFormatUtil.newFieldFormatUtil(map);
            return GcFilenum.builder()
                    .id_v(field.getString(  "id"))
                    .mid(field.getString( "mid"))
                    .topid(field.getString( "topid"))
                    .flag(field.getString("flag"))
                    .nlevel(field.getInt( "nlevel"))
                    .str(field.getString( "str"))
                    .spstr(field.getString( "spstr"))
                    .content(field.getString("content"))
                    .createTime(new Date())
                    .projectId(field.getLong(CommonConstant.TableVersion.PROJECT_ID))
                    .build();
        }
    
        public static FilenumConvert newFilenumConvert() { return new FilenumConvert();}
    
    }
    
    

    다른 생략.
    변환 함수 호출
      FilenumConvertFunction
    package com.lyc.postgresql.convert;
    
    import com.lyc.postgresql.common.EntityFunction;
    import com.lyc.postgresql.common.EntityModel;
    import com.lyc.postgresql.targetDataConvert.FilenumConvert;
    
    import java.util.Map;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/4/4 16:14
     * @description: FilenumConvert Function
     **/
    public class FilenumConvertFunction implements EntityFunction {
    
        @Override
        public EntityModel convertToEntity(Map<String, Object> map) {
            FilenumConvert filenumConvert = FilenumConvert.newFilenumConvert();
            return filenumConvert.formatToEntity(map);
        }
        
    }
    
    

    다른 생략.
    repository
      FilenumRepository
    package com.lyc.postgresql.repository;
    
    import com.lyc.postgresql.entity.GcFilenum;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    /**
     * Filenum Repository
     */
    public interface FilenumRepository extends JpaRepository<GcFilenum,Long> {
    }
    
    

    다른 생략.
    service
      CollectionRepositoryService
    package com.lyc.postgresql.service;
    
    import com.google.common.collect.Lists;
    import com.lyc.postgresql.convert.*;
    import com.lyc.postgresql.repository.*;
    import com.lyc.postgresql.common.EntityFunction;
    import com.lyc.postgresql.common.EntityRepository;
    import com.lyc.postgresql.sqlServer.tables.Tables;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/30 9:53
     * @description:      Repository  
     **/
    @Service
    public class CollectionRepositoryService {
    
        @Autowired
        InterfaceRepository interfaceRepository;
        @Autowired
        FilenumRepository filenumRepository;
        
        //    
    
    
        /**
         *      Repository  
         * @return
         */
        public List<EntityRepository> getRepositories(){
    
            List<EntityRepository> entityRepositoryList = Lists.newArrayList();
    
            //   Interface
            EntityFunction interfaceFunction = new InterfaceConvertFunction();
            EntityRepository interfaceEntityRepository = EntityRepository.builder()
                    .tableName(Tables.INTERFACE.getTableName())
                    .jpaRepository(interfaceRepository)
                    .entityFunction(interfaceFunction)
                    .build();
    
            //   filenum
            EntityFunction filenumFunction = new FilenumConvertFunction();
            EntityRepository filenumEntityRepository = EntityRepository.builder()
                    .tableName(Tables.FILENUM.getTableName())
                    .jpaRepository(filenumRepository)
                    .entityFunction(filenumFunction)
                    .build();
    
            //    
    
            //      
            entityRepositoryList.add(interfaceEntityRepository);
            entityRepositoryList.add(filenumEntityRepository);
            
            //    。
    
            return entityRepositoryList;
        }
    
    }
    
    

      CopyCoreService
    package com.lyc.postgresql.service;
    
    import com.google.common.collect.Lists;
    import com.lyc.postgresql.common.CommonConstant;
    import com.lyc.postgresql.common.EntityFunction;
    import com.lyc.postgresql.common.EntityModel;
    import com.lyc.postgresql.common.EntityRepository;
    import com.lyc.postgresql.feign.ItemFeignClient;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ExecutorService;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/28 18:55
     * @description:      PostgreSQL      (        )
     **/
    @SuppressWarnings("ConstantConditions")
    @Slf4j
    @Service
    public class CopyCoreService {
    
        @Autowired
        CollectionRepositoryService collectionRepositoryService;
    
        public void copyCore(ExecutorService executorService, ItemFeignClient personFeignClient, String table, String sortedField, int start, int size) {
            executorService.execute(() -> {
                //       ,        
                List<EntityModel> entityModelList = Lists.newArrayList();
                //     ,        
                List<Map<String,Object>> entityList = personFeignClient.selectListPageQuery(table,sortedField,start,size);
                entityList.forEach(map -> {
                    log.info(map.toString());
                    //            
                    EntityModel entityModel = getEntityModel(map);
                    //                
                    entityModelList.add(entityModel);
                });
                if(entityModelList.size() > 0){  //      ,       
                    //         
                    choiceRepository(entityModelList,entityList);
                }
            });
        }
    
        /**
         *           
         * @param itemFeignClient Feign      
         * @param table   
         * @param sortedField     
         * @param start     
         * @param size     
         */
        public void copyCore(ItemFeignClient itemFeignClient, String table, String sortedField, int start, int size, Long projectId) {
            //       ,        
            List<EntityModel> entityModelList = Lists.newArrayList();
            //     ,        
            List<Map<String,Object>> entityList = itemFeignClient.selectListPageQuery(table,sortedField,start,size);
            entityList.forEach(map -> {
                //  map    projectId
                map.put(CommonConstant.TableVersion.PROJECT_ID,projectId);
                log.info(map.toString());
                //            
                EntityModel entityModel = getEntityModel(map);
                //                
                entityModelList.add(entityModel);
            });
            if(entityModelList.size() > 0){  //      ,       
                //         
                choiceRepository(entityModelList,entityList);
            }
        }
    
        /**
         *        ,         
         * @param entityModelList
         * @param entityList
         */
        @HystrixCommand(
                fallbackMethod = "copyFallback"   //         
        )
        private void choiceRepository(List<EntityModel> entityModelList, List<Map<String, Object>> entityList) {
            //         
            String tableName = (String) entityList.get(0).get("tableName");
            //      EntityRepository  
            List<EntityRepository> entityRepositoryList = collectionRepositoryService.getRepositories();
            //     ,         ,         
            entityRepositoryList.forEach(entityRepository -> {
                //         ,        。
                if(tableName.equals(entityRepository.getTableName())){
                    JpaRepository jpaRepository = entityRepository.getJpaRepository();
                    //          
                    jpaRepository.save(entityModelList);
                }
            });
        }
    
        /**
         *            
         * @param map
         * @return
         */
        private EntityModel getEntityModel(Map<String,Object> map) {
            //         
            String tableName = (String) map.get("tableName");
            //           
            List<EntityModel> entityList = Lists.newArrayList();
            //      EntityRepository  
            List<EntityRepository> entityRepositoryList = collectionRepositoryService.getRepositories();
            entityRepositoryList.forEach(entityRepository -> {
                //         ,        。
                if(tableName.equals(entityRepository.getTableName())){
                    //     ,        
                    EntityFunction entityFunction = entityRepository.getEntityFunction();
                    EntityModel entityModel = entityFunction.convertToEntity(map);
                    entityList.add(entityModel);
                }
            });
            //        
            return entityList.get(0);
        }
    
        /**
         *    ,              
         */
        private void copyFallback(ExecutorService executorService, ItemFeignClient ItemFeignClient, String table, String sortedField, int start, int size){
            log.info("-------------------------------------        !-----------------------------");
            log.info("       :{}",table);
            log.info("-------------------------------------        !-----------------------------");
        }
    
    }
    
    

      PostgreSQLService
    package com.lyc.postgresql.service;
    
    import com.lyc.postgresql.common.NumberThreads;
    import com.lyc.postgresql.feign.ItemFeignClient;
    import com.lyc.postgresql.sqlServer.CollectionTables;
    import com.lyc.postgresql.sqlServer.tables.Tables;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.Date;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/28 9:11
     * @description: PostgreSQL Service
     **/
    @Slf4j
    @Service
    public class PostgreSQLService {
    
        @Autowired
        ItemFeignClient itemFeignClient;
        @Autowired
        CopyCoreService copyCoreService;
        @Autowired
        NumberThreads threads;
    
        /**
         *         
         * @param table
         * @return
         */
        public int countFrom(String table) {
            return itemFeignClient.countFrom(table);
        }
    
        /**
         *     SQLServer    PostgreSQL 
         * @param table       
         * @param sortedField     
         * @param projectId
         * @return
         */
        public boolean copyFrom(String table, String sortedField, Long projectId) {
            //        
            int total = itemFeignClient.countFrom(table);
            if(total != 0){   //          0,         ,       
                //              ,           
                //traversePerson(total,table,sortedField);
                //      
                traverseWithoutThreadPool(total,table,sortedField,projectId);
            }
            //       ,         
            return true;
        }
    
        /**
         *         
         * @param total     
         * @param table   
         * @param sortedField     
         * @param projectId
         */
        private void traverseWithoutThreadPool(int total, String table, String sortedField, Long projectId) {
            //           
            int lastCount = 0;
            //            
            int cycleTime = Integer.valueOf(threads.getCycleTime());
            //         
            int threadCount = 0;
            // 1、                 ,        
            if(total < cycleTime){
                //       
                threadCount = 1;
            } else {   // 2、               
                //            
                lastCount = total % cycleTime;
                if(lastCount == 0){   // 2.1、          =      /      
                    threadCount = total / cycleTime;
                } else {  // 2.2、            =      /       + 1
                    threadCount = total / cycleTime + 1;
                }
            }
    
            for(int i = 1; i <= threadCount; i ++){     //         
                //          
                final int start = (i - 1) * cycleTime;
                // 1、  threadCount 1
                if(threadCount == 1){
                    //              
                    copyCoreService.copyCore(itemFeignClient,table,sortedField,start, total, projectId);
                } else {  // 2、  threadCount  1
                    if(i < threadCount){ // 2.1、          ,            
                        copyCoreService.copyCore(itemFeignClient,table,sortedField,start, cycleTime, projectId);
                    } else {  // 2.2、         ,          
                        final int size = total - start;
                        copyCoreService.copyCore(itemFeignClient,table,sortedField,start, size, projectId);
                    }
                }
            }
        }
    
        /**
         *            
         * @return
         */
        public boolean copy() {
            //  SQLServer         
            CollectionTables collectionTables = CollectionTables.newCollectionTables();
            List<Tables> tableList = collectionTables.getTables();
            //              id
            final Long projectId = new Date().getTime();
            tableList.forEach(table -> {
                //          SQLServer    PostgreSQL 
                copyFrom(table.getTableName(),table.getSortedField(),projectId);
            });
            return true;
        }
    
        /**
         *     person
         * @param total       
         * @param sortedField     
         * @param table   
         */
        private void traversePerson(int total, String table, String sortedField){
            //           
            int lastCount = 0;
            //            
            int cycleTime = Integer.valueOf(threads.getCycleTime());
            //          
            int numberThreads = Integer.valueOf(threads.getNumberThreads());
            //         
            int threadCount = 0;
            //      (      )              ,  ,     ,   
            ExecutorService executorService = Executors.newFixedThreadPool(numberThreads);
    
            // 1、                 ,        
            if(total < cycleTime){
                //       
                threadCount = 1;
            } else {   // 2、               
                //            
                lastCount = total % cycleTime;
                if(lastCount == 0){   // 2.1、          =      /      
                    threadCount = total / cycleTime;
                } else {  // 2.2、            =      /       + 1
                    threadCount = total / cycleTime + 1;
                }
            }
    
            for(int i = 1; i <= threadCount; i ++){     //         
                //          
                final int start = (i - 1) * cycleTime;
                // 1、  threadCount 1
                if(threadCount == 1){
                    //              
                    copyCoreService.copyCore(executorService,itemFeignClient,table,sortedField,start, total);
                } else {  // 2、  threadCount  1
                    if(i < threadCount){ // 2.1、          ,            
                        copyCoreService.copyCore(executorService,itemFeignClient,table,sortedField,start, cycleTime);
                    } else {  // 2.2、         ,          
                        final int size = total - start;
                        copyCoreService.copyCore(executorService,itemFeignClient,table,sortedField,start, size);
                    }
                }
            }
            executorService.shutdown();
        }
    
    }
    
    

    controller
      PostgreSQLController
    package com.lyc.postgresql.controller;
    
    import com.lyc.postgresql.service.PostgreSQLService;
    import com.lyc.postgresql.util.TimeFormatUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/28 9:10
     * @description: PostgreSQL Controller
     **/
    @RestController
    public class PostgreSQLController {
    
        @Autowired
        PostgreSQLService postgreSQLService;
    
        /**
         *         
         * @param table
         * @return
         */
        @GetMapping("/countFrom/{table}")
        public int countFrom(@PathVariable("table") String table){
            return postgreSQLService.countFrom(table);
        }
    
        /**
         *            
         * @return
         */
        @GetMapping("/copy")
        public String copy(){
            TimeFormatUtil timeFormatUtil = TimeFormatUtil.newTimeFormatUtil();
            //         
            timeFormatUtil.setStartTime();
            //   
            boolean flag = postgreSQLService.copy();
            //         
            timeFormatUtil.setEndTime();
            //     
            String spendTime = timeFormatUtil.getSpendTime();
            //         
            return flag ? "      !" + spendTime : "      !";
        }
    
    }
    
    

    Bootstrap 시작 클래스
      PostgreSQLApplication
    package com.lyc.postgresql;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.feign.EnableFeignClients;
    import org.springframework.cloud.netflix.hystrix.EnableHystrix;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * @author: zhangzhenyi
     * @date: 2019/3/26 22:14
     * @description: PostgreSQL Bootstrap    
     **/
    @SpringBootApplication
    @EnableEurekaClient
    @EnableCircuitBreaker
    @EnableFeignClients
    @EnableHystrix
    public class PostgreSQLApplication {
    
        @LoadBalanced
        @Bean
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(PostgreSQLApplication.class,args);
        }
    
    }
    
    

    프로필
      application.yml
    spring:
      application:
        #     
        name: postgresql-server
      datasource:
        # spring       
        driverClassName: org.postgresql.Driver
        url: jdbc:postgresql://localhost:5432/gs
        username: postgres
        password: root
    # jpa           
      jpa:
        show-sql: true
        hibernate:
          ddl-auto: update
          use-new-id-generator-mappings: true
      jackson:
        serialization:
          indent_output: false
    
    #      
    server:
      port: 8083
    
    eureka:
      instance:
        #     IP              。  Eureka                
        prefer-ip-address: true
      client:
        register-with-eureka: true
        fetch-registry: true
        service-url:
          defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
    
    ### mybatis config ###
    mybatis:
      type-aliases-package: com.lyc.postgresql.entity
    
    # Hystrix    
    hystrix:
      command:
        default:
          execution:
            timeout:
              enabled: false
    
    ribbon:
      ReadTimeout: 120000
      ConnectTimeout: 60000
    

      application.properties
    #       
    thread.numberTreads=10
    #       ,             
    pagequery.cycleTime=100
    

    실행 결과
        이것 의 운행 은 비교적 간단 하 므 로 아래 의 경 로 를 직접 방문 하면 된다.
    http://localhost:8083/copy
    

        데이터 의 양 이 비교적 많 기 때문에 나머지 는 옆에서 묵묵히 기다 리 는 것 이다. 가끔 콘 솔 을 주시 하고 프로젝트 데이터 이동 의 진 도 를 살 펴 보 는 것 이다.

    좋은 웹페이지 즐겨찾기