Column'username'in field list isambiguous, 메일 누출 등 문제 분석 및 해결

질문 1.Column 'username' in field list is ambiguous
### The error may involve com.fx.oa.module.per.leave.api.shared.domain.PositiveEntity.queryListForPage-Inline
### The error occurred while setting parameters
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'username' in field list is ambiguous
; SQL []; Column 'username' in field list is ambiguous; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolat
오늘 정식 시스템이 업데이트된 후에 새 작업을 열었는데 페이지에 500 오류가 발생했습니다.로그를 여는 데 위의 오류가 있습니다.문제를 처리하는 엔지니어가 나에게 테스트 시스템 데이터와 코드에userName이라는 필드를 추가한 동료가 있을 수 있지만 정식 시스템 데이터베이스 업데이트표 구조에서 발생한 것은 아니라고 말했다.나는 로그 정보를 받았는데, 이 단어의 뜻은username이라는 필드가 명확하지 않고 다른 뜻이 있다는 것을 보았다.이러한 오류는 종종 여러 테이블 간의 관련 조회이며, 테이블에는 같은 필드 이름이 있으며, 이 필드에 속한 테이블을 지정하지 않아서 일어난다.새 작업 페이지의 밑에 역사를 조회하고 처리하는 표가 있습니다.기록을 조회할 때 모든 작업을 먼저 꺼냅니다. 작업의 승인자는 사용자 이름을 저장하기 때문에 사용자 테이블에 더 연결하여 사용자 이름을 꺼냅니다. 다음과 같습니다.
SELECT 
			task.processExecutionId,
			process.name as processDefineName,
			task.activityName,
			user.userName as createUserCode,
			task.status,
			task.description,
			task.finishTime,
			task.createTime
		FROM T_BPM_PROCESS_TASK task
		LEFT JOIN T_BPM_PROCESS_EXECUTION execution ON task.processExecutionId = execution.id
		LEFT JOIN t_bpm_process_define process ON execution.processDefineId = process.id
		LEFT JOIN T_SYS_USER user ON task.createUserCode = user.userCode
		WHERE task.processExecutionId = #{id}
		ORDER BY task.createTime DESC, task.finishTime DESC

이 버전의 오프라인에서 우리는 고급 조회의 사용자 관리 권한 제어를 기반으로 새로운 오프라인을 개설하였으며, 책임지는 듀공은 t_bpm_process_define에 두 개의 필드가 추가되었습니다. 그는 이미 존재하는 roleCode, roleName을 본떠서userCode,userName 두 개의 필드를 추가했습니다. 이 두 필드는 적어도 파일과 사용자 관련 테이블에서 널리 사용됩니다.그 중 이 두 필드는 우리 시스템에서 보존자로 간주될 수 있으며, 다른 표는 가능한 한 사용하지 말아야 한다.나는 이 두 개의 고급 검색에 사용되는 필드에 접두사를 붙일 것을 건의합니다. sql를 수정할 필요가 없습니다.
표 구조가 수정된 후에 이 문제는 사라졌다.
문제sql: 캡처 중 문제
이번 OA는 정식 시스템이 출시된 후moss시스템과 한동안 병행했다.이 기간 동안 oa의 모든 절차와 표는 테스트이고 정식 영수증은moss에 기입한다.그래서 우리는 절차의 표시 이름에 폼 페이지에 모두 "(테스트)"글자를 추가했고 페이지에 "(테스트)"글자가 포함된 폼은 작성하고 심사할 때 "이 폼은 테스트 폼입니다. 모스에 기입해 주십시오"라고 알립니다.3월 12일은 OA 폼이 정식으로 사용됩니다. 모든 테스트 글자를 시스템에서 지워야 합니다.테스트 문자가 추가될 때 각 프로세스의 담당 동료가 시스템 전단에 수동으로 추가하고 저장합니다.시스템 페이지의 모든 폼에서 삭제를 열면 매우 번거롭습니다.관찰을 통해 나는 모든 프로세스의 표시 이름이 (테스트 증빙서류) 또는 (테스트 문자) 을 포함하고 수십 개의 프로세스가 이름에 상기 글자를 포함하지 않은 것을 발견했다.테스트 영수증의 html와template에는 (테스트 폼), 그래서 다음 sql를 썼습니다.
update t_bpm_process_define set name=SUBSTR(NAME FROM 1 FOR INSTR(name,"( )")-1) where INSTR(name,"( )")!=0;
update t_bpm_form_define set template=REPLACE(template, '( )','')where INSTR(template,'( )')!=0;
update t_bpm_form_define set html=REPLACE(html, '<span style="color:#ff0000;">( )</span>','')where INSTR(html,'<span style="color:#ff0000;">( )</span>')!=0;

집행 후 표에는 문제가 없지만 첫 번째 문장의 집행에 무서운 현상이 나타나 많은 절차 명칭이 비어 있다.
첫 번째 문장에서 나는 문자열의 캡처를 사용했고, 두 번째, 세 번째 문장은 모두 부분 문자열을 교체했다.나는 처음에 이것과 관련이 있을 수 있다고 생각했는데, 실제로도 확실히 관련이 있다. 만약에 나도 Replace 함수를 사용한다면 문제가 없을 것이다. 이유는 매우 간단하다. 만약 텍스트에 목표 문자열이 포함되지 않는다면 틀림없이 바꾸지 않을 것이다.그러나 문자열 캡처는 논리적으로도 통할 수 있는데 왜 이렇게 무서운 결과가 나왔을까?
왜냐하면 우리가 업데이트를 사용할 때 테이블 연결을 사용하지 않았기 때문이다. ql가 실행할 때 어떤 데이터를 수정해야 하는지에 대한 데이터가 전혀 없다.
만약 우리가 첫 번째 데이터를 이렇게 수정한다면 문제없다.
update t_bpm_process_define a,(select id,name from t_bpm_proces_define where  INSTR(name,"( )")!=0) )b set a.name=SUBSTR(NAME FROM 1 FOR INSTR(name,"( )")-1) where a.id = b.id;

질문우리 회사가 사용하는 메일 서버는 지브라 서버이기 때문에 클라우드 컴퓨팅 부서에서 구매하고 유지보수합니다.OA의 알림 메일도 짐브라를 통해 밖으로 보냅니다.일부 특정 시간대의 대량의 메일, 예를 들어 기한 초과 작업과 출근 이상 등은 모두 특정한 시간대에quartz가 촉발하고 수백 통에서 수천 통의 메일을 발송한다.성숙한 상용 메일 서버에 대한 스트레스는 아무것도 아닐 수도 있지만, 짐브라에 대해서는 견딜 수 없을 것이다.클라우드 컴퓨팅과 IT 동료의 협조를 받아 메일 서버를 테스트했습니다. 테스트 용례는 다음과 같습니다.
테스트 용례 1:100봉, 총 사용 시 약:16min;실수 97통, 실패 3회, 오류 메시지 3회 모두:javax.mail.MessagingException: Could not connect to SMTP host
테스트 용례 2:100봉, 총 사용 시간: 16min;실수 100통, 실패 2회, 실수 동상.실패 재발급 메커니즘을 추가하고 실패 후 10s 재발급을 기다리며 최대 3회 재발급합니다.
테스트 용례 3: 한 통씩 보내고 10s에 머무르며 총 사용 시 32min;실수 100통, 실패 1회, 오류 동일;재발 메커니즘 동용례 2.
MessagingException에 대한 질문:
나는 몇 가지 해석을 보았다.인터넷;2. 방화벽;3. 서버의 자기 보호, 예를 들어 대량의 발송을 방지할 때 끊거나 스팸메일을 보내는 것을 방지한다. 나는 세 번째 해석이 믿을 만하다고 생각한다.
나중에 또 다른 압력 강도 테스트를 했고 Messaging Exception의 오류에 대해 한 걸음 한 걸음 코드를 추적하여 관련 분석을 실시했다
구체적인 오류 정보는 다음과 같습니다.
javax.mail.MessagingException:   Could   not   connect   to   SMTP   host:   mail.cn.phicomm.com,   port:   25;     nested   exception   is:                 java.net.SocketException:   Software   caused   connection   abort:   connect                 at   com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1282)                 at   com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:37 0)                 at   javax.mail.Service.connect(Service.java:297)                 at   javax.mail.Service.connect(Service.java:156)                 at   javax.mail.Service.connect(Service.java:105) 
코드를 읽어봤는데 이렇게 됐어요. 우선 서버 Socket을 연결합니다.
	if (serverSocket != null)
			openServer(); // only happens from connect(socket) else
							// openServer(host, port);
		else
			openServer(host, port);

다음은 openServer의 코드입니다.
if (debug) 
			out.println("DEBUG SMTP: got bad greeting from host \"" + 
		    server + "\", port: " + 
		    port + ", response: " + 
		    r + "
");  throw new MessagingException( "Got bad greeting from SMTP host: " + server +  ", port: " +  port + ", response: " +  r);  }

debug는 전역 변수로session의 속성입니다. 그 값입니다.
Since the debug setting can be turned on only after the Session has been created
즉, 세션이 만들어지지 않으면 Messaging Exception이라는 오류를 보고합니다.그래서 나는 우리가 보낸 메일 코드가 매번 인증을 다시 연결한다고 의심했다. 이것도 코드의 문제 중 하나이기 때문에 나는session이 효력을 잃어서 다시 연결했다.
다음 테스트를 한 번 더 진행했습니다. 용례는 다음과 같습니다.
용례코드 수정은 다음과 같습니다.
	if (session == null || session.getDebug()) {
			System.out.println(" " + j + " ");
			session = Session.getDefaultInstance(prop, auth);
		}

결과: 실패 없음
용례여전히 1의 코드를 사용하고,
결과: 그러나 1회 실패했고, 실패 후session을 다시 얻지 못했으며, 실패 후session은 여전히 유효하다는 것을 알 수 있다.
용례코드 수정은 다음과 같습니다.
if (session == null || session.getDebug()) {
			//  , 
			if (mail.isValidate()) {
				auth = new MailAuthenticator(mail.getUserName(),
						mail.getPassword());
			}
			System.out.println(" " + j + " ");
			session = Session.getDefaultInstance(prop, auth);
		}

결과: 한 번의 실패가 있었고, 실패 후 다시 연결되지 않았다.
상기 테스트를 통해 매번 세션을 다시 얻는 것이 효율에 영향을 미치지 않고 이상 발생에도 영향을 미치지 않는지 여부입니다.이상이 보고된 후에도 세션은 유효하며 재발급할 수 있습니다.
세 차례의 테스트를 통해 사실 우리는 재발급 메커니즘이 이미 우편물의 완전한 송달을 보장할 수 있다는 것을 발견할 수 있다.
다시 보낸 코드는 다음과 같습니다.
/**
		 * Temporary mechanism: automatic resend mail
		 * @author chao.gao
		 * @date 2015-2-4  9:27:59
		 * @param mail
		 * @return
		 */
		public static boolean sendHtmlMail(BasicMail mail){
			
			if(sendHtmlMail_(mail)){
				return true;
			} else{
				int i = 0;
				while(!sendHtmlMail_(mail) && i < 3){				
					try {	
						i++;
						Thread.sleep(1000*60);
					} catch (InterruptedException e) {
						LOGGER.error("resend mail error", e);	
					}
				}
				return true;
			}
		}

재발 메커니즘에 가입하여 한동안 운행하였으나 유사한 누출 현상을 다시 발견하지 못했다.

좋은 웹페이지 즐겨찾기