码迷,mamicode.com
首页 > 其他好文 > 详细

Column 'username' in field list is ambiguous、邮件漏发等问题的分析及解决

时间:2015-03-13 19:10:18      阅读:2349      评论:0      收藏:0      [点我收藏+]

标签:ambiguou 内连接 邮件

问题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的字段,但没有在正式系统数据库更新表结构导致的。我拿到日志信息,看到是ambiguous,这个单词的意思是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。

表结构修改后该问题消失。

问题2.sql:截取中出现的问题

  本期OA在正式系统上线后,与moss系统并行了一段时间。在这段时间里oa的所有流程及表单均为测试,正式单据在moss里填写。所以我们在流程的显示名称在表单页面均添加了“(测试)”字样,而且页面中凡包含“(测试)”字样的表单,在填写和审批时都会提示“该表单是测试表单,请到moss里填写”。312号是OA表单正式启用,需要将所有的测试字样从系统里抹去。在测试字样添加的时候,由各流程负责同事在系统前端手动添加和保存。如果再在系统页面每张表单打开删除会非常麻烦。经过观察,我发现所有流程的显示名都包含(测试单据)或(测试字样),且几十个流程均未有在名称中包含以上字样。而在测试单据的htmltemplate中,均包含<span style="color:#ff0000;">(测试表单)</span>所以我写了以下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函数是没有问题的,原因很简单,如果文本中不包含目标字符串肯定是不会替换的。但用字符串截取从逻辑上也讲得通,为什么会出现这么可怕的结果呢?

  原因就在于我们update没有使用表内联,sql在执行的时候根本没有什么数据去关联它到底该修改哪条数据。

  如果我们将第一条数据修改成这样,就没有问题了:

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;

问题3.由于我们公司使用的邮件服务器是Zimbra服务器,由云计算部门购买和维护。OA中的提醒邮件也是通过Zimbra往外发送。对于一些某时段的大批量邮件,比如逾期工作和考勤异常都是在某个时间点上由quartz触发,同时会发出数百封以至上千封邮件。可能对成熟的商用邮件服务器这点压力算不上什么,但对于Zimbra可能已经吃不消了。在云计算和IT的同事协助下,由我对邮件服务器进行了测试,测试用例如下:


测试用例1:100封,总用时约:16min;实收97封,失败3次,3次错误信息均为:javax.mail.MessagingException: Could not connect to SMTP host


测试用例2100封,总用时约:16min;实收100封,失败2次,错误同上。加失败重发机制,失败后等待10s重发,最多重发3次;


测试用例3:每发一封,停留10s,总用时32min;实收100封,失败1次,错误同上;重发机制同用例2.

  关于MessagingException的问题:

  我看了一下几种解释:1.网络;2.防火墙;3.服务器的自我保护,比如防止大批量发送时挂掉或者垃圾邮件,我觉得第三种解释靠谱一些。

后来又做了一些其他压力强度的测试,而且针对MessagingException的错误,一步步跟踪代码,也进行了相关分析

  具体错误信息如下:

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) 

  我通读了一下代码,发现是这样的,首先会连接生成serverSocket

	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 + "\n"); 
			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

  也就是说session未建立就会报MessagingException这个错误。所以我进一步怀疑,我们的发送邮件代码每次都会去重连认证,这个也是代码的问题之一,所以我加了session失效才重连。

  接下来又进行了一次测试,用例如下:

用例1.代码修改如下

	if (session == null || session.getDebug()) {
			System.out.println("第" + j + "次重连");
			session = Session.getDefaultInstance(prop, auth);
		}

结果:没有失败

用例2.仍用1的代码,

结果:但失败1次,失败后未重新获得session,可见失败后session仍有效;

用例3.代码修改如下:

if (session == null || session.getDebug()) {
			// 如果需要身份验证,创建一个账号密码验证器
			if (mail.isValidate()) {
				auth = new MailAuthenticator(mail.getUserName(),
						mail.getPassword());
			}
			System.out.println("第" + j + "次重连");
			session = Session.getDefaultInstance(prop, auth);
		}

结果:有1次失败,失败后未重连。

  通过以上测试,是否每次重新获得session对效率 没有影响,对异常的发生也没有影响。异常报出后,session仍有效,并且可以重发。

  经过三轮测试,其实我们可以发现重发机制已经可以保证邮件的完全送达。

重发的代码如下:

/**
		 * 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;
			}
		}

  加入重发机制运行了一段时间,未再发现类似的漏发现象。








本文出自 “南湖矿工技术空间” 博客,请务必保留此出处http://jncumter.blog.51cto.com/812546/1620095

Column 'username' in field list is ambiguous、邮件漏发等问题的分析及解决

标签:ambiguou 内连接 邮件

原文地址:http://jncumter.blog.51cto.com/812546/1620095

(1)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!