场景

项目框架情况:

          SpringMVC + MybatisPlus + msyql...

需求:

           从sqlserver数据库中同步产品和产品类别两个表的数据。

 

思路

1、利用 java自带的java.sql.Connection 与sqlserver数据库建立连接。

2、通过Apache的dbutils工具类QueryRunner( org.apache.commons.dbutils.QueryRunner)来获取sqlserver中的对应数据。

3、分析转化上述数据至我们需要的数据。

4、通过本地项目中的mysql数据源(或者步骤1中同样的方式),与msyql建立连接。

5、批量插入、更新mysql中的数据。

 

代码

1、数据源连接工具类DbConnUtil

package com.platform.syncdatabase.util;

import com.platform.utils.ResourceUtil;

import java.sql.Connection;
import java.sql.DriverManager;


public class DbConnUtil {

    private static String sqlserverDriverClassName = ResourceUtil.getConfigByName("hy.jindie.sqlserverDriverClassName");
    private static String sqlserverDbUrl = ResourceUtil.getConfigByName("hy.jindie.sqlserverDbUrl");
    private static String sqlserverDbUser = ResourceUtil.getConfigByName("hy.jindie.sqlserverDbUser");
    private static String sqlserverDbPwd = ResourceUtil.getConfigByName("hy.jindie.sqlserverDbPwd");

    /**
     * 从这里取数据
     *
     * @return
     */
    public static Connection createConnSrc() {
        Connection conn = null;
        try {
            Class.forName(sqlserverDriverClassName).newInstance();
            conn = DriverManager.getConnection(sqlserverDbUrl, sqlserverDbUser, sqlserverDbPwd);
        } catch (Exception e) {
            e.printStackTrace();

        }
        return conn;
    }


    /**
     * 存入的目标数据库
     *
     * @return
     */
    public static Connection createConnDist() {
        Connection conn = null;
        try {
            String driverClassName = "com.mysql.jdbc.Driver";
            String dbUrl = "jdbc:mysql://192.168.1.110:3306/haoyuan?useUnicode=true&characterEncoding=UTF-8";
            String dbUser = "root";
            String dbPwd = "1234567890";
            Class.forName(driverClassName).newInstance();
            conn = DriverManager.getConnection(dbUrl, dbUser, dbPwd);
        } catch (Exception e) {
            e.printStackTrace();

        }

        return conn;
    }


    public static void close(Connection conn) {
        try {
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

}

2、Apache dbutils QueryRunner数据操作工具类的封装类DbBuilder

 

package com.platform.syncdatabase;


import com.platform.syncdatabase.util.DbConnUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;

import java.sql.Connection;
import java.util.List;
import java.util.Map;

public class DbBuilder {
    Connection connection = null;

    public DbBuilder(Connection conn) {
        this.connection = conn;
    }


    public QueryRunner getQueryRunner() {
        return new QueryRunner();
    }

    /**
     * 根据传入的sql,查询记录,以Map形式返回第一行记录 注意:如果有多行记录,只会返回第一行,所以使用场景需要注意,可以使用根据主键来查询的场景
     *
     * @param sql
     * @param params
     * @return
     */
    public Map<String, Object> getFirstRowMap(String sql, Object... params) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.query(connection, sql, new MapHandler(), params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }


    /**
     * 根据传入的sql查询数据,以List Map形式返回
     *
     * @param sql
     * @param params
     * @return
     */
    public List<Map<String, Object>> getListMap(String sql, Object... params) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.query(connection, sql, new MapListHandler(), params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 根据sql和对象,查询结果并以对象形式返回
     *
     * @param sql
     * @param type
     * @return
     */
    public <T> T getBean(String sql, Class<T> type) {
        try {
            QueryRunner runner = getQueryRunner();
            return runner.query(sql, new BeanHandler<T>(type));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 根据sql和对象,查询结果并以对象形式返回
     *
     * @param sql
     * @param type
     * @return
     */
    public <T> T getBean(Connection connection, String sql, Class<T> type) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.query(connection, sql, new BeanHandler<T>(type));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }


    /**
     * 根据sql和对象,查询结果并以对象形式返回
     *
     * @param sql
     * @param type
     * @param params
     * @return
     */
    public <T> T getBean(Connection connection, String sql, Class<T> type, Object... params) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.query(connection, sql, new BeanHandler<T>(type), params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }


    /**
     * 根据sql查询list对象
     *
     * @param sql
     * @param type
     * @return
     */
    public <T> List<T> getListBean(Connection connection, String sql, Class<T> type) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.query(connection, sql, new BeanListHandler<T>(type));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 根据sql查询list对象
     *
     * @param sql
     * @param type
     * @param params
     * @return
     */
    public <T> List<T> getListBean(String sql, Class<T> type, Object... params) {
        try {
            QueryRunner runner = getQueryRunner();
            return runner.query(sql, new BeanListHandler<T>(type), params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 根据sql查询list对象
     *
     * @param sql
     * @param type
     * @param params
     * @return
     */
    public <T> List<T> getListBean(Connection connection, String sql, Class<T> type, Object... params) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.query(connection, sql, new BeanListHandler<T>(type), params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 保存操作
     *
     * @param sql
     * @param params
     * @return
     */
    public int save(String sql, Object... params) {
        try {
            QueryRunner runner = getQueryRunner();
            return runner.update(connection, sql, params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return 0;
    }

    /**
     * 保存操作
     *
     * @param sql
     * @param params
     * @return
     */
    public int save(Connection connection, String sql, Object... params) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.update(connection, sql, params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return 0;
    }

    /**
     * 更新操作
     *
     * @param sql
     * @param params
     * @return
     */
    public int update(String sql, Object... params) {
        try {
            QueryRunner runner = getQueryRunner();
            return runner.update(sql, params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return 0;
    }

    /**
     * 更新操作
     *
     * @param sql
     * @param params
     * @return
     */
    public int update(Connection connection, String sql, Object... params) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.update(connection, sql, params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return 0;
    }

    /**
     * 删除操作
     *
     * @param sql
     * @param params
     * @return
     */
    public int delete(String sql, Object... params) {
        try {
            QueryRunner runner = getQueryRunner();
            return runner.update(sql, params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return 0;
    }

    /**
     * 删除操作
     *
     * @param sql
     * @param params
     * @return
     */
    public int delete(Connection connection, String sql, Object... params) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.update(connection, sql, params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return 0;
    }

    /**
     * 批量操作,包括批量保存、修改、删、	 *
     *
     * @param sql
     * @param params
     * @return
     */
    public int[] batch(String sql, Object[][] params) {
        try {
            QueryRunner runner = getQueryRunner();
            return runner.batch(sql, params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 批量操作,包括批量保存、修改、删处	 *
     *
     * @param sql
     * @param params
     * @return
     */
    public int[] batch(Connection connection, String sql, Object[][] params) {
        try {
            QueryRunner runner = new QueryRunner();
            return runner.batch(connection, sql, params);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * �?��事务
     */
    public void beginTransaction(Connection conn) {
        try {
            conn.setAutoCommit(false);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 回滚事务
     */
    public void rollback(Connection conn) {
        try {
            conn.rollback();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 提交事务
     */
    public void commit(Connection conn) {
        try {
            conn.commit();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        try {

            Connection conn = DbConnUtil.createConnDist();
            DbBuilder b = new DbBuilder(conn);
            System.out.println(b.save("insert into demo_test(id,kitchen) values(?,?)", "11", "11"));
            DbConnUtil.close(conn);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3、数据同步类DoDataSycn,以下同步中对mysql中已存在的数据进行更新时可以先与sqlserver中的数据对比版本变化,只更新有变化的数据即可。此处由于sqlserver数据库的数据版本信息不可用所以取消了对比,而是全量更新。

package com.platform.syncdatabase;

import com.platform.entity.CategoryEntity;
import com.platform.entity.GoodsEntity;
import com.platform.service.CategoryService;
import com.platform.service.GoodsService;
import com.platform.syncdatabase.util.DbConnUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.sql.Connection;
import java.util.*;

@Slf4j
public class DoDataSycn {

    @Autowired
    CategoryService categoryService;

    @Autowired
    GoodsService goodsService;

    /**
     * 更新品类
     */
    public void updateCategory() {
        //打开链接
        Connection connSqlserver = DbConnUtil.createConnSrc();
        DbBuilder sqlserver = new DbBuilder(connSqlserver);
        try {
            //DO
            //DO 1、遍历mysql数据。添加map id为key
            //DO 2、遍历sqlserver数据获取新增数据添加插入map,获取修改过的数据添加update map
            //DO 3、实现批量更新功能
            String sql = "Select * from t_Item WHERE FItemClassID = 4";
            List<Map<String, Object>> remoteList = sqlserver.getListMap(sql, null);//获取远程金蝶数据
            if (remoteList != null && !remoteList.isEmpty()) {
                List<CategoryEntity> insertList = new ArrayList<>();
                List<CategoryEntity> updateList = new ArrayList<>();
                //查询mysql现有品类
                List<CategoryEntity> mysqlCategoryList = categoryService.queryList(new HashMap<>());
                if (mysqlCategoryList != null && !mysqlCategoryList.isEmpty()) {//已存在数据时,对比更新
                    //1、现有数据分析整理
                    Map<String, CategoryEntity> mysqlCategoryMap = new HashMap<>();
                    for (CategoryEntity category : mysqlCategoryList) {
                        mysqlCategoryMap.put(category.getId() + "", category);
                    }
                    //获取现有id
                    Set<String> ids = mysqlCategoryMap.keySet();
                    log.info("ids.size() " + ids.size());

                    //2、开始对比数据
                    //遍历金蝶数据
                    for (Map item : remoteList) {
                        try {
                            String id = item.get("FItemID") + "";
                            if (ids.contains(id)) {//已存在的品类 更新
                                updateList.add(copyCategoryInfo(item, mysqlCategoryMap.get(id)));
                            } else {//新增的品类
                                insertList.add(copyCategoryInfo(item, new CategoryEntity()));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                } else {//初始化全量插入
                    for (Map item : remoteList) {
                        try {
                            insertList.add(copyCategoryInfo(item, new CategoryEntity()));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                try {
                    if (!insertList.isEmpty()) {
                        log.info(("saveBatch category " + insertList.size()));
                        categoryService.saveBatch(insertList);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

                try {
                    if (!updateList.isEmpty()) {
                        log.info(("batchUpdate category " + updateList.size()));
                        categoryService.batchUpdate(updateList);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭
            DbConnUtil.close(connSqlserver);
        }

    }

    /**
     * 更新品类信息
     *
     * @param item
     * @param categoryEntity
     * @return
     */
    private CategoryEntity copyCategoryInfo(Map item, CategoryEntity categoryEntity) {
        categoryEntity.setId(Integer.parseInt(item.get("FItemID") + ""));
        categoryEntity.setName(item.get("FName") + "");
        categoryEntity.setParentId(Integer.parseInt(item.get("FParentID") + ""));
        categoryEntity.setSortOrder(Integer.parseInt(item.get("FShortNumber") + ""));
        String fDeleted = item.get("FDeleted") + "";
        if (StringUtils.isNotBlank(fDeleted) && "1".equals(fDeleted)) {
            categoryEntity.setIsShow(0);
        } else {
            categoryEntity.setIsShow(1);
        }
        categoryEntity.setLevel(item.get("FLevel") + "");
        categoryEntity.setFlevel(Integer.parseInt(item.get("FLevel") + ""));
        categoryEntity.setFullnumber(item.get("FFullNumber") + "");
        categoryEntity.setFullname(item.get("FFullName") + "");
        categoryEntity.setUuid(item.get("UUID") + "");
        //拼接ModifyTime
        byte[] fModifyTimes = (byte[]) item.get("FModifyTime");
        StringBuilder modifyTime = new StringBuilder();
        for (byte b : fModifyTimes) {
            modifyTime.append(b);
        }
        categoryEntity.setModifyTime(modifyTime.toString());//添加更新版本信息
        categoryEntity.setIsGood((boolean) item.get("FDetail") ? "1" : "0");
        return categoryEntity;
    }


    /**
     * 更新产品
     */
    public void updateGoods() {
        //打开链接
        Connection connSqlserver = DbConnUtil.createConnSrc();
        DbBuilder sqlserver = new DbBuilder(connSqlserver);
        try {
            //DO
            //DO 1、遍历mysql数据。添加map id为key
            //DO 2、遍历sqlserver数据获取新增数据添加插入map,获取修改过的数据添加update map
            //DO 3、实现批量更新功能
            String sql = "SELECT" +
                    " i.FItemID," +
                    " c.FName," +
                    " i.FParentID," +
                    " i.FShortNumber," +
                    " i.FDeleted," +
                    " i.FLevel," +
                    " i.FFullNumber," +
                    " i.FFullName," +
                    " i.UUID," +
                    " i.FModifyTime," +
                    " c.FOrderPrice," +
                    " c.FOrderPrice," +
                    " c.FOrderPrice," +
                    " c.FModel " +
                    "FROM " +
                    " t_item i" +
                    " LEFT JOIN t_icitemcore c ON i.FItemID = c.FItemID " +
                    "WHERE " +
                    " i.FItemClassID = 4 " +
                    " AND i.FDetail = 1 ;";
//                    " AND i.FDetail = 1 "+
//                    " AND i.FItemID = 291;";
            List<Map<String, Object>> remoteList = sqlserver.getListMap(sql, null);//获取远程金蝶数据
            if (remoteList != null && !remoteList.isEmpty()) {
                List<GoodsEntity> insertList = new ArrayList<>();
                List<GoodsEntity> updateList = new ArrayList<>();
                //查询mysql现有产品
                List<GoodsEntity> mysqlGoodsList = goodsService.queryAllGoods();
                if (mysqlGoodsList != null && !mysqlGoodsList.isEmpty()) {//已存在数据时,对比更新
                    //1、现有数据分析整理
                    Map<String, GoodsEntity> mysqlGoodsMap = new HashMap<>();
                    for (GoodsEntity goods : mysqlGoodsList) {
                        mysqlGoodsMap.put(goods.getId() + "", goods);
                    }
                    //获取现有id
                    Set<String> ids = mysqlGoodsMap.keySet();

                    //2、开始对比数据
                    //遍历金蝶数据
                    for (Map item : remoteList) {
                        try {
                            String id = item.get("FItemID") + "";
                            if (ids.contains(id)) {//已存在的品类
                                //更新
                                updateList.add(copyGoodsInfo(item, mysqlGoodsMap.get(id)));
                            } else {//新增的品类
                                insertList.add(copyGoodsInfo(item, new GoodsEntity()));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                } else {//初始化全量插入
                    for (Map item : remoteList) {
                        try {
                            insertList.add(copyGoodsInfo(item, new GoodsEntity()));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                try {
                    if (!insertList.isEmpty()) {
                        log.info(("saveBatch goods " + insertList.size()));
                        goodsService.saveBatch(insertList);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

                try {
                    if (!updateList.isEmpty()) {
                        log.info(("batchUpdate goods " + updateList.size()));
                        goodsService.batchUpdate(updateList);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭
            DbConnUtil.close(connSqlserver);
        }

    }


    /**
     * 更新产品信息
     *
     * @param item
     * @param goodsEntity
     * @return
     */
    private GoodsEntity copyGoodsInfo(Map item, GoodsEntity goodsEntity) {
        goodsEntity.setId(Integer.parseInt(item.get("FItemID") + ""));
        goodsEntity.setName(item.get("FName") + "");
        goodsEntity.setCategoryId(Integer.parseInt(item.get("FParentID") + ""));
        goodsEntity.setSortOrder(Integer.parseInt(item.get("FShortNumber") + ""));
        String fDeleted = item.get("FDeleted") + "";
        if (StringUtils.isNotBlank(fDeleted) && "1".equals(fDeleted)) {
            goodsEntity.setIsDelete(0);
        } else {
            goodsEntity.setIsDelete(1);
        }
        goodsEntity.setFlevel(Integer.parseInt(item.get("FLevel") + ""));
        goodsEntity.setFullnumber(item.get("FFullNumber") + "");
        goodsEntity.setFullname(item.get("FFullName") + "");
        goodsEntity.setUuid(item.get("UUID") + "");
        //拼接ModifyTime
        byte[] fModifyTimes = (byte[]) item.get("FModifyTime");
        StringBuilder modifyTime = new StringBuilder();
        for (byte b : fModifyTimes) {
            modifyTime.append(b);
        }
        goodsEntity.setModifyTime(modifyTime.toString());//添加更新版本信息
        goodsEntity.setCounterPrice(new BigDecimal(item.get("FOrderPrice") + ""));
        goodsEntity.setRetailPrice(new BigDecimal(item.get("FOrderPrice") + ""));
        goodsEntity.setUnitPrice(new BigDecimal(item.get("FOrderPrice") + ""));
        goodsEntity.setModel(item.get("FModel") + "");
        return goodsEntity;
    }


}

4、项目properties配置文件中的sqlserver连接信心配置

#sqlserver连接信息
hy.jindie.sqlserverDriverClassName = net.sourceforge.jtds.jdbc.Driver
hy.jindie.sqlserverDbUrl =  jdbc:jtds:sqlserver://192.168.1.111:1433;DatabaseName=haoyuan
hy.jindie.sqlserverDbUser = sa
hy.jindie.sqlserverDbPwd =  123213214123