JAVA开发(对大表数据逐条进行处理踩的坑记录一下)

 

一、编程语言介绍

所使用的编程语言为JAVA。纯后端开发。

二、炫技代码分享

 现在我编写代码一般通过逆向工程生成,只需要设计好数据库表就可以逆向生成后端的接口模块。

三、案例分享

逆向工程。逆向工程涉及到的输出模块。具体运用需要关注和联系博主分享使用。

## 该工程的意义
- 该工程的主要好处是解决开发人员编写重复的代码, 
- 强制开发人员使用规范的编程模式和代码注解,  
- 提高代码的可维护性和阅读性,
- 降低了代码的不规范性和因个人编程缺陷引起的不必要风险,  
- 提高代码质量和开发效率。  

## 使用说明
- 1、修改dbConfig.xml文件配置数据源信息。  
- 2、修改project.xml文件配置微服务信息。  
    2.0、修改name为对应数据库,支持mysql、oracle、postgresql  
    2.1、修改schema为据库名称  
    2.2、修改table为表名,多个表以逗号分隔  
    2.3、修改version版本号  
    2.4、修改author为自己的OA名称  
    2.5、修改service为服务名称  
    2.6、修改module为模块名称  
    2.7、修改rootPackage为根包名称  
    2.8、修改application为启动类名称  
    2.9、其他内容无需修改  
- 3、运行Run.java,生成代码,路径为out目录下 。  

<?xml version="1.0" encoding="GBK"?>
<project>
	<import resource="dbConfig.xml" />
	<configuration>
		<prop key="defaultEncoding">UTF-8</prop>
		<prop key="outputEncoding">UTF-8</prop>
		<!-- 可通过设置不同的模板路径,生成对应的不同模板代码-->
		<prop key="templateDir">{root}/template</prop>
		
	</configuration>

	<templates>
		<template name="application">mhyr/application.ftl</template>
		<template name="baseApplication">mhyr/base-application.ftl</template>
		<template name="bootstrap">mhyr/bootstrap.ftl</template>
		<template name="app">mhyr/app.ftl</template>
		<template name="entity">mhyr/entity.ftl</template>
		<template name="dto">mhyr/dto.ftl</template>
		<template name="client">mhyr/client.ftl</template>
		<template name="constant">mhyr/constant.ftl</template>
		<template name="controller">mhyr/controller.ftl</template>
		<template name="service">mhyr/service.ftl</template>
		<template name="dao">mhyr/dao.ftl</template>
		<template name="cache">mhyr/cache.ftl</template>
		<template name="parentPom">mhyr/parent-pom.ftl</template>
		<template name="modulePom">mhyr/module-pom.ftl</template>
		<template name="target">mhyr/target.ftl</template>
	</templates>
	<rules>
		<rule name="tableName" type="JavaScript">
			<![CDATA[
            function convertTableName(tableName) {
                var a = tableName.split('_');
                if (a.length > 1) {
                    //a.shift();
                }
                var tempStr;
                for (var i = 0, len = a.length; i < len; i++) {
                    tempStr = a[i];
                    a[i] = tempStr.charAt(0).toUpperCase() + tempStr.substring(1).toLowerCase();
                }
                return a.join('');
            }
            ]]>
		</rule>
		<rule name="columnName" type="JavaScript">
			<![CDATA[
            function convertColumnName(columnName) {
                var a = columnName.split('_');
                if (a.length > 1) {
                    //a.shift();
                }
                var tempStr;
                for (var i = 0, len = a.length; i < len; i++) {
                    tempStr = a[i];
                    if (i == 0) {
                        a[i] = tempStr.toLowerCase();
                    } else {
                        a[i] = tempStr.charAt(0).toUpperCase() + tempStr.substring(1).toLowerCase();
                    }
                }
                return a.join('');
            }
            ]]>
		</rule>
	</rules>
	<inputs>
		<input>
			<source type="db">
				<!-- 支持mysql、oracle、postgresql -->
				<db name="postgressql">
					<!-- oracle为用户名(大写); mysql,postgresql为库名 -->
					<prop key="schema">public</prop>
					<!-- oracle要大写; 多个表中间用','隔开 -->
					<prop key="table">m_token_user</prop>
				</db>
			</source>
			<custom>
				<!--版本-->
				<prop key="version">1.0</prop>
				<!--作者-->
				<prop key="author">茅河野人</prop>
				<!--系统名称-->
				<prop key="system">maoheyeren-plat</prop>
				<!--服务名称-->
				<prop key="service">member-business</prop>
				<!--启动类名-->
				<prop key="application">Token</prop>
				<!--根包名称-->
				<prop key="rootPackage">cn.mhyr.member</prop>
				<!--client包名称-->
				<prop key="clientPackage">{rootPackage}.client</prop>
				<!--constant包名称-->
				<prop key="constantPackage">{rootPackage}.constant</prop>
				<!--controller包名称-->
				<prop key="controllerPackage">{rootPackage}.controller</prop>
				<!--dao包名称-->
				<prop key="daoPackage">{rootPackage}.dao</prop>
				<!--dto包名称-->
				<prop key="dtoPackage">{rootPackage}.dto</prop>
				<!--entity包名称-->
				<prop key="entityPackage">{rootPackage}.entity</prop>
				<!--dto包名称-->
				<prop key="dtoPackage">{rootPackage}.dto</prop>
				<!--service包名称-->
				<prop key="servicePackage">{rootPackage}.service</prop>
				<!--application包名称-->
				<prop key="applicationPackage">{rootPackage}/{application}</prop>
				<!--缓存包名-->
				<prop key="cachePackage">{rootPackage}.cache</prop>
			</custom>

			<outputs outputDir="{root}/out">
				<!--生成服务包-->
				<output name="base" subOutputDir="{service}/{service}/src/main/java/" template="entity" package-name="{entityPackage}">
					<rule>
						<prop key="tableName">tableName</prop>
						<prop key="columnName">columnName</prop>
					</rule>
					<filePattern>{package-name}/{class-name}.java</filePattern>
				</output>
				
				<output extends="base" subOutputDir="{service}/{service}/src/main/java/" template="dto" package-name="{dtoPackage}">
					<filePattern>{package-name}/{class-name}DTO.java</filePattern>
				</output>
				<!--
				<output extends="base" subOutputDir="{service}/{service}/src/main/java/" template="client" package-name="{clientPackage}">
					<filePattern>{package-name}/{class-name}Client.java</filePattern>
				</output>
		        -->
				<output extends="base" subOutputDir="{service}/{service}/src/main/java/" template="constant" package-name="{constantPackage}">
					<filePattern>{package-name}/{class-name}Constant.java</filePattern>
				</output>
				
				<output extends="base" subOutputDir="{service}/{service}/src/main/java/" template="controller" package-name="{controllerPackage}">
					<filePattern>{package-name}/{class-name}Controller.java</filePattern>
				</output>

				<output extends="base" subOutputDir="{service}/{service}/src/main/java/" template="service" package-name="{servicePackage}">
					<filePattern>{package-name}/{class-name}Service.java</filePattern>
				</output>
				
				<output extends="base" subOutputDir="{service}/{service}/src/main/java/" template="dao" package-name="{daoPackage}">
					<filePattern>{package-name}/{class-name}Mapper.java</filePattern>
				</output>
				
				<output extends="base" subOutputDir="{service}/{service}/src/main/java/" template="baseApplication" package-name="{applicationPackage}">
					<filePattern>{package-name}Application.java</filePattern>
				</output>
				
				<output extends="base" subOutputDir="{service}/{service}/" template="modulePom" package-name="">
					<filePattern>pom.xml</filePattern>
				</output>
				
				<output extends="base" subOutputDir="{service}/{service}/src/main/resources/" template="bootstrap" package-name="">
					<filePattern>bootstrap.yml</filePattern>
				</output>
				 
				<output extends="base" subOutputDir="{service}/{service}/src/main/resources/" template="application" package-name="">
					<filePattern>application.yml</filePattern>
				</output>
				
				<output extends="base" subOutputDir="{service}/{service}/src/main/resources/META-INF" template="app" package-name="">
					<filePattern>app.properties</filePattern>
				</output>
				
				<output extends="base" subOutputDir="{service}/{service}/target" template="target" package-name="">
					<filePattern>target-test.txt</filePattern> 
				</output>
				
				<output extends="base" subOutputDir="{service}/{service}/src/main/java/" template="cache" package-name="{cachePackage}">
							<filePattern>{package-name}/{class-name}Cache.java</filePattern>
				</output>
		 
			</outputs>
		</input>
	</inputs>
</project>

四、如何学习高级技术

高级的技术总是让人感觉简洁。

 

五、介绍对大表数据逐条处理遇到的坑

背景:

有一批数据需要解密,数据量500W,需要导到pg数据库中。

处理方式:

通过Java代码,逐条读取数据进行处理,将处理结果更新。

编写代码:

使用 ApplicationRunner 线程

线程类:

 

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import cn.ctg.member.service.TmpMUserService;
 
import lombok.extern.slf4j.Slf4j;

/**
 * 线程服务类
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class ToolServiceThread implements ApplicationRunner {
    
//	@Autowired
//	private HongkongPhoneService hongkongPhoneService;
	//ExecutorService threadPool = Executors.newFixedThreadPool(2);
	
	@Autowired
	private GenerateUrllinkClient generateUrllinkClient;
	@Autowired
	private WeixinAppService weixinAppService;
	
	@Autowired
	private TmpMUserService tmpMUserService;

	@Override
	public void run(ApplicationArguments args) throws Exception {
		log.info("开启线程.....,");
		tmpMUserService.updateOne();
		
	}
 
}

解密数据服务类。 

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.ctg.common.encryption.SHAUtils;
import cn.ctg.common.encryption.SM4Util;
import cn.ctg.member.dao.TmpMUserMapper;
import cn.ctg.member.entity.MUserSf;
import cn.ctg.member.entity.TmpMUser;
import lombok.extern.slf4j.Slf4j;

 
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class TmpMUserService extends ServiceImpl<TmpMUserMapper, TmpMUser> {

	@Autowired
	private TmpMUserMapper tmpMUserMapper;

	private String keyString = "秘钥";
	private String pre = "86-s4:";

	public TmpMUser getOne() {
		return tmpMUserMapper.selectTmpMUser();
	}

	public void updateOne() {

		
		for (int i = 0; i < 5000000; i++) {
			TmpMUser tmpMUser = getOne();
			if (null != tmpMUser) {
				String yphone = tmpMUser.getPhone();
				log.info("原手机号:"+yphone);
				if(!StringUtils.isEmpty(yphone)) {
					yphone = yphone.replaceFirst(pre, "");
					String phone = SM4Util.sm4Decode(yphone, keyString);
					String origPhone = SHAUtils.getSHA("86-" + phone);
					log.info("解密出手机号:"+phone);	
					tmpMUser.setPhone(phone);
					tmpMUser.setOrigPhone(origPhone);
					//tmpMUserMapper.updateById(tmpMUser);
					tmpMUserMapper.updateTmpMUser(tmpMUser.getUserId(), phone, origPhone);
				 
				  
				}
			
			}
		 
			log.info("已解密数据条数:"+i);
			
		}
	

	}
}

关键代码:



import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import cn.ctg.member.entity.TmpMUser;

  
@Repository
public interface TmpMUserMapper extends BaseMapper<TmpMUser> {
	
    /**
     * 更新字段
     */
    @Update("<script>" +
            "update 数据表  SET phone = #{phone},orig_phone =#{origPhone}  WHERE user_id = #{userId} ; commit " +
            "</script>")
    public void updateTmpMUser(@Param("userId") String userId,@Param("phone") String phone,@Param("origPhone") String origPhone);
    
    /**
     * 查询
     */
    @Select("<script>" +
            "select  *  from 数据表 where orig_phone is null and  phone is not null limit 1 " +
            "</script>")
    public TmpMUser selectTmpMUser();
    
   
}

讲解:

select  *  from 数据表 where orig_phone is null and  phone is not null limit 1;

这个语句就能从数据表一条条读数据,通过代码不可能把500W条数据全部加载到内存中处理。所以这里需要 limit  1.

"update 数据表  SET phone = #{phone},orig_phone =#{origPhone}  WHERE user_id = #{userId} ; commit 

这个语句对表进行更新,并commit 。 这里记住一定要显式commit ,如果没commit,pg数据表数据是不会更新的。 这就是这一次踩的坑。 

猜你喜欢

转载自blog.csdn.net/dongjing991/article/details/130849654