Java + jsf 实现 仿百度 全拼 简拼 汉字智能补全

项目需求客户要求录入人员信息时人员的企业名称是可以用拼音模糊匹配的就和百度类似,比如说客户输入"qd"或者"qingdao"或者汉字"青岛"就要把以“青岛”开头的企业全部列出来。

以下是借助pinyin4j-2.5.0.jar的实现方法

首先是数据库 

company_info表  企业信息表  包括企业名称 companyname

pinyincode表 有id,hz(汉字),qp(全拼),jp(简拼) 四个字段

hz 字段存企业名称 gp,jp分别存储 企业名称对应的全拼和简拼 

对于多音字存多条记录 例如

id           hz                               qp                        jp

1          单田芳                  dantianfang                 dtf
2          单田芳                  shantianfang               stf
3          单田芳                 chantianfang                ctf

查询的时候只要

select * from  company_info c where c.companyname in(select p.hz  from pinyincode p where p.hz like'?%' or p.qp like'?%' or p. jp like'?%')

?号处为输入的查询条件  这样不管输入全拼,简拼还是汉字 都能把所要的信息查出来

只需要保存企业信息的时候 把企业名称的拼音码存在pinyincode表里即可

之所以额外设计一个pinyincode表有两个原因 

1是多音字

 2可能以后还有其他地方要用到这种查询方式到时候只要把需要查询的字段保存时也存一份在pinyincode表里即可   设计其他业务表的表结构时完全不需要考虑这方面的需求。

那么如何把企业名称转化成全拼和简拼那 这个就要用到 pinyin4j了 pinyin4j官方网址:http://pinyin4j.sourceforge.net/ 

以下是代码

package com.sdunicomsi.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

public class PinYinUtils {
 
 /**
  * 输入汉字获取该汉字的拼音HashMap key为全拼,value为简拼
  * @param src
  * @return
  */
 public static HashMap<String, String> getPinyin(String src){
  if(src!=null && !src.trim().equalsIgnoreCase("")){
   char[] srcChar ;
   srcChar=src.toCharArray();
   //汉语拼音格式输出类
   HanyuPinyinOutputFormat hanYuPinOutputFormat = new HanyuPinyinOutputFormat();

//输出设置,大小写,音标方式等
   hanYuPinOutputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); 
   hanYuPinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
   hanYuPinOutputFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
   
   String[][] qp_temp = new String[src.length()][];//全拼
   String[][] jp_temp = new String[src.length()][];//首字母简拼
   for(int i=0;i<srcChar.length;i++){
    char c = srcChar[i];
    //是中文或者a-z或者A-Z转换拼音(我的需求,是保留中文或者a-z或者A-Z)
    if(String.valueOf(c).matches("[\\u4E00-\\u9FA5]+")){//判断中文
     try{
    	 qp_temp[i] = PinyinHelper.toHanyuPinyinStringArray(c, hanYuPinOutputFormat);
    	 jp_temp[i]= new String[qp_temp[i].length];
    	 for(int k=0;k<qp_temp[i].length;k++){
    		 jp_temp[i][k]=""+qp_temp[i][k].charAt(0);
    	 }
     }catch(BadHanyuPinyinOutputFormatCombination e) {
      e.printStackTrace();
     }
    }else if(((int)c>=65 && (int)c<=90) || ((int)c>=97 && (int)c<=122)){//判断字母
    	qp_temp[i] = new String[]{String.valueOf(srcChar[i])};
    	jp_temp[i] = qp_temp[i];
    }else{
    	qp_temp[i] = new String[]{""};
    	jp_temp[i] = qp_temp[i];
    }
   }
   
   HashMap<String, String> map= DoExchange(qp_temp,jp_temp);

   return map;
  }
  return null;
 }
 

   
    /**
     * 递归
     * @param strJaggedArray
     * @return HashMap<String, String>
     * key全拼,value简拼
     */
	private static HashMap<String, String> DoExchange(String[][] qp_pyArrar,String[][] jp_pyArrar){
        int len = qp_pyArrar.length;
        if(len >= 2){           
            int qp_len1 = qp_pyArrar[0].length;
            int qp_len2 = qp_pyArrar[1].length;
            int qp_newlen = qp_len1*qp_len2;
            String[] qp_temp = new String[qp_newlen];
            String[] jp_temp = new String[qp_newlen];
            int Index = 0;
            for(int i=0;i<qp_len1;i++){
                for(int j=0;j<qp_len2;j++){
                	qp_temp[Index] = qp_pyArrar[0][i] + qp_pyArrar[1][j];
                	jp_temp[Index] = jp_pyArrar[0][i] + jp_pyArrar[1][j];
                    Index ++;
                }
            }
            String[][] qp_newArray = new String[len-1][];
            String[][] jp_newArray = new String[len-1][];
            for(int i=2;i<len;i++){
            	qp_newArray[i-1] = qp_pyArrar[i]; 
            	jp_newArray[i-1]= jp_pyArrar[i];
            } 
            qp_newArray[0] = qp_temp;
            jp_newArray[0] = jp_temp;
            return DoExchange(qp_newArray,jp_newArray);
        }else{
        	HashMap<String, String> map = new HashMap<String, String>();
        	for(int i=0;i<qp_pyArrar[0].length;i++){
        		map.put(qp_pyArrar[0][i], jp_pyArrar[0][i]);
        	}
         return map;   
        }
    }
   
 /**
  * @param args
  */
 public static void main(String[] args) {
  String str = "单田芳";
  HashMap<String, String> map=getPinyin(str);
	Iterator<Entry<String,String>> iter = map.entrySet().iterator(); 
	   while (iter.hasNext()) { 
	       Entry<String,String> entry = (Entry<String,String>) iter.next(); 
	       String qp = entry.getKey();
	       String jp = entry.getValue(); 
           System.out.println(qp+","+jp);
	   }
}
}

以上代码在http://wister.iteye.com/blog/334562 这篇文章的基础上做了简单的修改 在此感谢wister

运行 输出结果为

 dantianfang,dtf
shantianfang,stf
chantianfang,ctf
我们保存company_info表时 只需 获取企业名称对应的全拼简拼map 遍历存在 pinyincode表里就可以了,当然存之前最好判断一下 pinyincode表里是不是已经存在该企业名称的拼音码了避免重复。

jsp页面(使用jsf标签)

					<td align="left" width="70" class="border-bottom-css nowrap-css">
							<h:outputText value="企业名称"></h:outputText>
						</td>
						<td align="left" width="200" class="border-bottom-css nowrap-css">
							<h:panelGroup>
							<h:inputText id="splicenceName_test" value="#{user.entity.company.name}" style="margin:0px;" ></h:inputText>
								<h:graphicImage value="/resource/images/arrow.png" οnclick="#{rich:component('suggestion')}.callSuggestion(true)"
                                 alt="" />
                            </h:panelGroup>
							<rich:suggestionbox height="300" width="265" fetchValue="#{result.name}" usingSuggestObjects="true"
							for="splicenceName_test" var="result" suggestionAction="#{user.autocomplete}"
							onobjectchange="processObjects(suggestion)" id="suggestion"  >
							<f:facet name="header">
							<rich:columnGroup>
								<rich:column>
									<h:outputText value="ID"></h:outputText>
								</rich:column>
								<rich:column>
									<h:outputText value="企业名称"></h:outputText>
								</rich:column>
							</rich:columnGroup>
							</f:facet>
							<h:column>
               				<h:outputText value="#{result.id}" />
            				</h:column>
							<h:column>
							<h:outputText value="#{result.name}" />
							</h:column>
							</rich:suggestionbox>
							<h:inputHidden id="splicenceId" value="#{user.entity.company.id}"></h:inputHidden>
						</td>

js

	     function processObjects(sgcomponent){
           
               document.getElementById("v1:detail:subForm:splicenceId").value = sgcomponent.getSelectedItems().pluck('id');
            }

后台bean

	public List <SplicenceEntity> autocomplete(Object suggest) {
		String pref = (String)suggest;
		
		List <SplicenceEntity> list = splicenceManager.getSplicenceByInput(pref);
	
		  return list;
	}

最终效果图





 

 

service

package com.sdunicomsi.typt.service.companyinfo;



import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sdunicomsi.org.springside.modules.orm.Page;
import com.sdunicomsi.typt.dao.companyinfo.PinyinCodeDao;
import com.sdunicomsi.typt.entity.companyinfo.PinyinCodeEntity;
import com.sdunicomsi.util.PinYinUtils;


/**
 * 
 * @funId pinyincode
 * @date 2013-07-25
 * @version 代码生成器2.1.8
 * @company 中国联通统集成有限公司山东分公司技术部
 *
 */
@Service
// 默认将类中的所有函数纳入事务管理.
@Transactional
public class  PinyinCodeManager {
	
	@Autowired
	private PinyinCodeDao dao;

	public PinyinCodeEntity getEntity(String id) {
		return dao.get(id);
	}

	public Page<PinyinCodeEntity> find(Page<PinyinCodeEntity> page, PinyinCodeEntity condition) {
		StringBuffer sql = new StringBuffer("select * from sp_pinyincode t where 1=1 ");
		if (condition.getJp() != null&& !condition.getJp().toString().trim().equals("")) {
			sql.append(" AND jp=").append(condition.getJp());
		}
		return dao.findBySql(page, sql.toString(), PinyinCodeEntity.class);
	}

	public boolean isExist(String hz,String qp){
		StringBuffer sql = new StringBuffer();
		sql.append("select * from sp_pinyincode t where t.hz = '").append(hz).append("'");
		sql.append(" and t.qp = '").append(qp).append("'");
		List<PinyinCodeEntity> list =  dao.findBySql(sql.toString(), PinyinCodeEntity.class);
		if(list!=null&&list.size()>0){
			return true;
		}else{
			return false;
		}
	}
	
	@Transactional
	public void delete(PinyinCodeEntity e) {
		dao.delete(e);

	}
    /**
     * lxg
     * @param hz
     */
	@Transactional
	public void save(String hz) {
		HashMap<String, String> map = PinYinUtils.getPinyin(hz);
		Iterator<Entry<String,String>> iter = map.entrySet().iterator(); 
		   while (iter.hasNext()) { 
		       Entry<String,String> entry = (Entry<String,String>) iter.next(); 
		       String qp = entry.getKey();
		       String jp = entry.getValue();
		       if(!isExist(hz,qp)){
		    	   PinyinCodeEntity entity = new PinyinCodeEntity();
		    	   entity.setHz(hz);
		    	   entity.setQp(qp);
		    	   entity.setJp(jp);
		   		   dao.save(entity);
		       }
		   }
	}
	
}


dao

package com.sdunicomsi.typt.dao.companyinfo;

import org.springframework.stereotype.Repository;

import com.sdunicomsi.org.springside.modules.orm.hibernate.HibernateDao;
import com.sdunicomsi.typt.entity.companyinfo.PinyinCodeEntity;

/**
 * 
 * @funId pinyincode
 * @date 2013-07-25
 * @version 代码生成器2.1.8
 * @company 中国联通统集成有限公司山东分公司技术部
 *
 */
@Repository
public class PinyinCodeDao extends HibernateDao<PinyinCodeEntity, String> {

	public PinyinCodeDao() {
		super();
	}
	
}


entity

package com.sdunicomsi.typt.entity.companyinfo;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

/**
 * 
 * @funId pinyincode
 * @date 2013-07-25
 * @version 代码生成器2.1.8
 * @company 中国联通统集成有限公司山东分公司技术部
 *
 */
@SuppressWarnings("serial")
@Entity()
@Table(name="sp_pinyincode")
@Cache(usage = CacheConcurrencyStrategy.NONE)
public class  PinyinCodeEntity implements Serializable {

	private String id;
	private String hz;//汉字
	private String jp;//简拼(首字母)
	private String qp;//全拼
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	public String getId() {
		return id;
	}
	
	public void setId(String id) {
		this.id = id;
	}
	
	public String getHz() {
		return hz;
	}
	
	public void setHz(String hz) {
		this.hz = hz;
	}

	public String getJp() {
		return jp;
	}
	
	public void setJp(String jp) {
		this.jp = jp;
	}

	public String getQp() {
		return qp;
	}
	
	public void setQp(String qp) {
		this.qp = qp;
	}

}


调用

	@Transactional
	public void save(SplicenceEntity entity) {
		pinyinCodeManager.save(entity.getName());
		dao.save(entity);
		
	}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值